/[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 2012 - (show annotations) (download)
Fri Oct 23 17:53:17 2009 UTC (14 years, 5 months ago) by iliev
File size: 6984 byte(s)
* Refactoring: moved the independent code from
  the Gigasampler format engine to base classes
* SFZ format engine: experimental code (not usable yet)
* SoundFont format engine: experimental code (not usable yet)
* Fixed crash which may occur when MIDI key + transpose is out of range

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_PCM_16:
53 case SF_FORMAT_DPCM_8:
54 case SF_FORMAT_DPCM_16:
55 FrameSize = sizeof(short) * ChannelCount;
56 break;
57 default:
58 FrameSize = sizeof(int) * ChannelCount;
59 }
60 TotalFrameCount = sfInfo.frames;
61
62 if(!DontClose) Close();
63 }
64
65 SampleFile::~SampleFile() {
66 Close();
67 }
68
69 void SampleFile::Open() {
70 if(pSndFile) return; // Already opened
71 SF_INFO sfInfo;
72 sfInfo.format = 0;
73 pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
74 if(pSndFile == NULL) throw Exception(File + ": Can't load sample");
75 #if CONFIG_DEVMODE
76 std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
77 #endif
78 }
79
80 void SampleFile::Close() {
81 if(pSndFile == NULL) return;
82 if(sf_close(pSndFile)) std::cerr << "Sample::Close() " << "Failed to close " << File << std::endl;
83 pSndFile = NULL;
84 #if CONFIG_DEVMODE
85 std::cout << "Number of opened sample files: " << --SampleFile_OpenFilesCount << std::endl;
86 #endif
87 }
88
89 long SampleFile::SetPos(unsigned long FrameOffset) {
90 return SetPos(FrameOffset, SEEK_SET);
91 }
92
93 long SampleFile::SetPos(unsigned long FrameCount, int Whence) {
94 if(pSndFile == NULL) {
95 std::cerr << "Sample::SetPos() " << File << " not opened" << std::endl;
96 return -1;
97 }
98
99 return sf_seek(pSndFile, FrameCount, Whence);
100 }
101
102 long SampleFile::GetPos() {
103 if(pSndFile == NULL) {
104 std::cerr << "Sample::GetPos() " << File << " not opened" << std::endl;
105 return -1;
106 }
107
108 return sf_seek(pSndFile, 0, SEEK_CUR);
109 }
110
111 Sample::buffer_t SampleFile::LoadSampleData() {
112 return LoadSampleDataWithNullSamplesExtension(this->TotalFrameCount, 0); // 0 amount of NullSamples
113 }
114
115 Sample::buffer_t SampleFile::LoadSampleData(unsigned long FrameCount) {
116 return LoadSampleDataWithNullSamplesExtension(FrameCount, 0); // 0 amount of NullSamples
117 }
118
119 Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(uint NullFrameCount) {
120 return LoadSampleDataWithNullSamplesExtension(this->TotalFrameCount, NullFrameCount);
121 }
122
123 Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(unsigned long FrameCount, uint NullFramesCount) {
124 Open();
125 if (FrameCount > this->TotalFrameCount) FrameCount = this->TotalFrameCount;
126 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
127 unsigned long allocationsize = (FrameCount + NullFramesCount) * this->FrameSize;
128 SetPos(0, SEEK_SET); // reset read position to begin of sample
129 RAMCache.pStart = new int8_t[allocationsize];
130
131 RAMCache.Size = Read(RAMCache.pStart, FrameCount) * this->FrameSize;
132 RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
133 // fill the remaining buffer space with silence samples
134 memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
135 Close();
136 return GetCache();
137 }
138
139 long SampleFile::Read(void* pBuffer, unsigned long FrameCount) {
140 Open();
141 if(FrameSize == sizeof(short) * ChannelCount) {
142 return sf_readf_short(pSndFile, (short*)pBuffer, FrameCount);
143 } else {
144 return sf_readf_int(pSndFile, (int*)pBuffer, FrameCount);
145 }
146 }
147
148 unsigned long SampleFile::ReadAndLoop (
149 void* pBuffer,
150 unsigned long FrameCount,
151 PlaybackState* pPlaybackState
152 ) {
153 // TODO:
154 SetPos(pPlaybackState->position);
155 Read(pBuffer, FrameCount);
156 pPlaybackState->position = GetPos();
157 }
158
159 void SampleFile::ReleaseSampleData() {
160 if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
161 RAMCache.pStart = NULL;
162 RAMCache.Size = 0;
163 RAMCache.NullExtensionSize = 0;
164 }
165
166 Sample::buffer_t SampleFile::GetCache() {
167 // return a copy of the buffer_t structure
168 buffer_t result;
169 result.Size = this->RAMCache.Size;
170 result.pStart = this->RAMCache.pStart;
171 result.NullExtensionSize = this->RAMCache.NullExtensionSize;
172 return result;
173 }
174 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC