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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2216 - (hide annotations) (download)
Mon Jul 25 17:21:16 2011 UTC (12 years, 9 months ago) by iliev
File size: 8641 byte(s)
* sfz: added support for sample offset (offset)

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003 - 2009 Christian Schoenebeck *
6 persson 2167 * Copyright (C) 2009 - 2011 Grigor Iliev *
7 iliev 2012 * *
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 persson 2119 #include "../../common/global_private.h"
26 iliev 2012 #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 persson 2119 switch(Format & SF_FORMAT_SUBMASK) {
51 iliev 2012 case SF_FORMAT_PCM_S8:
52     case SF_FORMAT_PCM_U8:
53 iliev 2019 case SF_FORMAT_DPCM_8:
54     FrameSize = ChannelCount;
55     break;
56 iliev 2012 case SF_FORMAT_PCM_16:
57     case SF_FORMAT_DPCM_16:
58 iliev 2019 FrameSize = 2 * ChannelCount;
59 iliev 2012 break;
60 iliev 2019 case SF_FORMAT_PCM_24:
61     case SF_FORMAT_DWVW_24:
62     FrameSize = 3 * ChannelCount;
63     break;
64 iliev 2012 default:
65 iliev 2019 FrameSize = 2 * ChannelCount;
66 iliev 2012 }
67     TotalFrameCount = sfInfo.frames;
68    
69 persson 2167 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 iliev 2012 if(!DontClose) Close();
85     }
86    
87     SampleFile::~SampleFile() {
88     Close();
89 persson 2058 ReleaseSampleData();
90 iliev 2012 }
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 iliev 2216
150     if (Offset > MaxOffset && FrameCount < TotalFrameCount) {
151     FrameCount = FrameCount + Offset > TotalFrameCount ? TotalFrameCount - Offset : FrameCount;
152     // Offset the RAM cache
153     RAMCacheOffset = Offset;
154     }
155 iliev 2012 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
156     unsigned long allocationsize = (FrameCount + NullFramesCount) * this->FrameSize;
157 iliev 2216 SetPos(RAMCacheOffset, SEEK_SET); // reset read position to playback start point
158 iliev 2012 RAMCache.pStart = new int8_t[allocationsize];
159    
160     RAMCache.Size = Read(RAMCache.pStart, FrameCount) * this->FrameSize;
161     RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
162     // fill the remaining buffer space with silence samples
163     memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
164     Close();
165     return GetCache();
166     }
167    
168     long SampleFile::Read(void* pBuffer, unsigned long FrameCount) {
169     Open();
170 persson 2119
171     // ogg files must be read with sf_readf, not sf_read_raw. On
172     // big endian machines, sf_readf_short is also used for 16 bit
173     // wav files, to get automatic endian conversion (for 24 bit
174     // samples this is handled in Synthesize::GetSample instead).
175    
176     #if WORDS_BIGENDIAN || HAVE_DECL_SF_FORMAT_VORBIS
177     if (
178     #if WORDS_BIGENDIAN
179     FrameSize == 2 * ChannelCount
180     #else
181     (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS
182     #endif
183     ) {
184     return sf_readf_short(pSndFile, static_cast<short*>(pBuffer), FrameCount);
185     } else
186     #endif
187     {
188     int bytes = sf_read_raw(pSndFile, pBuffer, FrameCount * GetFrameSize());
189     return bytes / GetFrameSize();
190     }
191 iliev 2012 }
192    
193     unsigned long SampleFile::ReadAndLoop (
194     void* pBuffer,
195     unsigned long FrameCount,
196     PlaybackState* pPlaybackState
197     ) {
198     // TODO:
199     SetPos(pPlaybackState->position);
200 iliev 2018 unsigned long count = Read(pBuffer, FrameCount);
201 iliev 2012 pPlaybackState->position = GetPos();
202 iliev 2018 return count;
203 iliev 2012 }
204    
205     void SampleFile::ReleaseSampleData() {
206     if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
207     RAMCache.pStart = NULL;
208     RAMCache.Size = 0;
209     RAMCache.NullExtensionSize = 0;
210     }
211    
212     Sample::buffer_t SampleFile::GetCache() {
213     // return a copy of the buffer_t structure
214     buffer_t result;
215     result.Size = this->RAMCache.Size;
216     result.pStart = this->RAMCache.pStart;
217     result.NullExtensionSize = this->RAMCache.NullExtensionSize;
218     return result;
219     }
220     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC