/[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 2058 - (show annotations) (download)
Sun Feb 14 11:40:49 2010 UTC (14 years, 2 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 /***************************************************************************
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 case SF_FORMAT_DPCM_8:
53 FrameSize = ChannelCount;
54 break;
55 case SF_FORMAT_PCM_16:
56 case SF_FORMAT_DPCM_16:
57 FrameSize = 2 * ChannelCount;
58 break;
59 case SF_FORMAT_PCM_24:
60 case SF_FORMAT_DWVW_24:
61 FrameSize = 3 * ChannelCount;
62 break;
63 default:
64 FrameSize = 2 * ChannelCount;
65 }
66 TotalFrameCount = sfInfo.frames;
67
68 if(!DontClose) Close();
69 }
70
71 SampleFile::~SampleFile() {
72 Close();
73 ReleaseSampleData();
74 }
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 int bytes = sf_read_raw(pSndFile, pBuffer, FrameCount * GetFrameSize());
149 return bytes / GetFrameSize();
150 }
151
152 unsigned long SampleFile::ReadAndLoop (
153 void* pBuffer,
154 unsigned long FrameCount,
155 PlaybackState* pPlaybackState
156 ) {
157 // TODO:
158 SetPos(pPlaybackState->position);
159 unsigned long count = Read(pBuffer, FrameCount);
160 pPlaybackState->position = GetPos();
161 return count;
162 }
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