/[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 2058 - (hide annotations) (download)
Sun Feb 14 11:40:49 2010 UTC (14 years, 3 months ago) by persson
File size: 7133 byte(s)
* sfz/sf2 engines: fixed memory leak and memory handling errors
* sfz engine: added support for sw_trigger=first, sw_trigger=legato
  and sw_previous
* sfz parser: allow non-numerical key values ("C#4" for example)
* sfz engine: "key" opcode now sets pitch_keycenter too
* sfz engine: fixed error when unloading instrument with same sample
  used by multiple regions
* sfz parser: added some opcode aliases, like loopmode for loop_mode,
  to be more compatible

1 iliev 2012 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003 - 2009 Christian Schoenebeck *
6     * Copyright (C) 2009 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/Exception.h"
26    
27     #include <cstring>
28    
29     namespace LinuxSampler {
30     #if CONFIG_DEVMODE
31     int SampleFile_OpenFilesCount = 0;
32     #endif
33    
34     SampleFile::SampleFile(String File, bool DontClose) {
35     this->File = File;
36     this->pSndFile = NULL;
37    
38     SF_INFO sfInfo;
39     sfInfo.format = 0;
40     pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
41     if(pSndFile == NULL) throw Exception(File + ": Can't get sample info: " + String(sf_strerror (NULL)));
42     #if CONFIG_DEVMODE
43     std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
44     #endif
45     SampleRate = sfInfo.samplerate;
46     ChannelCount = sfInfo.channels;
47     Format = sfInfo.format;
48    
49     switch(Format & 0xF) {
50     case SF_FORMAT_PCM_S8:
51     case SF_FORMAT_PCM_U8:
52 iliev 2019 case SF_FORMAT_DPCM_8:
53     FrameSize = ChannelCount;
54     break;
55 iliev 2012 case SF_FORMAT_PCM_16:
56     case SF_FORMAT_DPCM_16:
57 iliev 2019 FrameSize = 2 * ChannelCount;
58 iliev 2012 break;
59 iliev 2019 case SF_FORMAT_PCM_24:
60     case SF_FORMAT_DWVW_24:
61     FrameSize = 3 * ChannelCount;
62     break;
63 iliev 2012 default:
64 iliev 2019 FrameSize = 2 * ChannelCount;
65 iliev 2012 }
66     TotalFrameCount = sfInfo.frames;
67    
68     if(!DontClose) Close();
69     }
70    
71     SampleFile::~SampleFile() {
72     Close();
73 persson 2058 ReleaseSampleData();
74 iliev 2012 }
75    
76     void SampleFile::Open() {
77     if(pSndFile) return; // Already opened
78     SF_INFO sfInfo;
79     sfInfo.format = 0;
80     pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
81     if(pSndFile == NULL) throw Exception(File + ": Can't load sample");
82     #if CONFIG_DEVMODE
83     std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
84     #endif
85     }
86    
87     void SampleFile::Close() {
88     if(pSndFile == NULL) return;
89     if(sf_close(pSndFile)) std::cerr << "Sample::Close() " << "Failed to close " << File << std::endl;
90     pSndFile = NULL;
91     #if CONFIG_DEVMODE
92     std::cout << "Number of opened sample files: " << --SampleFile_OpenFilesCount << std::endl;
93     #endif
94     }
95    
96     long SampleFile::SetPos(unsigned long FrameOffset) {
97     return SetPos(FrameOffset, SEEK_SET);
98     }
99    
100     long SampleFile::SetPos(unsigned long FrameCount, int Whence) {
101     if(pSndFile == NULL) {
102     std::cerr << "Sample::SetPos() " << File << " not opened" << std::endl;
103     return -1;
104     }
105    
106     return sf_seek(pSndFile, FrameCount, Whence);
107     }
108    
109     long SampleFile::GetPos() {
110     if(pSndFile == NULL) {
111     std::cerr << "Sample::GetPos() " << File << " not opened" << std::endl;
112     return -1;
113     }
114    
115     return sf_seek(pSndFile, 0, SEEK_CUR);
116     }
117    
118     Sample::buffer_t SampleFile::LoadSampleData() {
119     return LoadSampleDataWithNullSamplesExtension(this->TotalFrameCount, 0); // 0 amount of NullSamples
120     }
121    
122     Sample::buffer_t SampleFile::LoadSampleData(unsigned long FrameCount) {
123     return LoadSampleDataWithNullSamplesExtension(FrameCount, 0); // 0 amount of NullSamples
124     }
125    
126     Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(uint NullFrameCount) {
127     return LoadSampleDataWithNullSamplesExtension(this->TotalFrameCount, NullFrameCount);
128     }
129    
130     Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(unsigned long FrameCount, uint NullFramesCount) {
131     Open();
132     if (FrameCount > this->TotalFrameCount) FrameCount = this->TotalFrameCount;
133     if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
134     unsigned long allocationsize = (FrameCount + NullFramesCount) * this->FrameSize;
135     SetPos(0, SEEK_SET); // reset read position to begin of sample
136     RAMCache.pStart = new int8_t[allocationsize];
137    
138     RAMCache.Size = Read(RAMCache.pStart, FrameCount) * this->FrameSize;
139     RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
140     // fill the remaining buffer space with silence samples
141     memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
142     Close();
143     return GetCache();
144     }
145    
146     long SampleFile::Read(void* pBuffer, unsigned long FrameCount) {
147     Open();
148 iliev 2019 int bytes = sf_read_raw(pSndFile, pBuffer, FrameCount * GetFrameSize());
149     return bytes / GetFrameSize();
150 iliev 2012 }
151    
152     unsigned long SampleFile::ReadAndLoop (
153     void* pBuffer,
154     unsigned long FrameCount,
155     PlaybackState* pPlaybackState
156     ) {
157     // TODO:
158     SetPos(pPlaybackState->position);
159 iliev 2018 unsigned long count = Read(pBuffer, FrameCount);
160 iliev 2012 pPlaybackState->position = GetPos();
161 iliev 2018 return count;
162 iliev 2012 }
163    
164     void SampleFile::ReleaseSampleData() {
165     if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
166     RAMCache.pStart = NULL;
167     RAMCache.Size = 0;
168     RAMCache.NullExtensionSize = 0;
169     }
170    
171     Sample::buffer_t SampleFile::GetCache() {
172     // return a copy of the buffer_t structure
173     buffer_t result;
174     result.Size = this->RAMCache.Size;
175     result.pStart = this->RAMCache.pStart;
176     result.NullExtensionSize = this->RAMCache.NullExtensionSize;
177     return result;
178     }
179     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC