1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003 - 2009 Christian Schoenebeck                       *
6  *   Copyright (C) 2009 - 2014 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 #define CONVERT_BUFFER_SIZE 4096
31 
32 namespace LinuxSampler {
33     #if CONFIG_DEVMODE
34     int SampleFile_OpenFilesCount = 0;
35     #endif
36 
SampleFile(String File,bool DontClose)37     SampleFile::SampleFile(String File, bool DontClose) {
38         this->File      = File;
39         this->pSndFile  = NULL;
40         pConvertBuffer  = NULL;
41 
42         SF_INFO sfInfo;
43         sfInfo.format = 0;
44         pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
45         if(pSndFile == NULL) throw Exception(File + ": Can't get sample info: " + String(sf_strerror (NULL)));
46         #if CONFIG_DEVMODE
47         std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
48         #endif
49         SampleRate = sfInfo.samplerate;
50         ChannelCount = sfInfo.channels;
51         Format = sfInfo.format;
52 
53         switch(Format & SF_FORMAT_SUBMASK) {
54             case SF_FORMAT_PCM_S8:
55             case SF_FORMAT_PCM_U8:
56             case SF_FORMAT_DPCM_8:
57                 FrameSize = ChannelCount;
58                 break;
59             case SF_FORMAT_PCM_16:
60             case SF_FORMAT_DPCM_16:
61                 FrameSize = 2 * ChannelCount;
62                 break;
63             case SF_FORMAT_PCM_24:
64             case SF_FORMAT_DWVW_24:
65             case SF_FORMAT_PCM_32:
66             case SF_FORMAT_FLOAT:
67                 FrameSize = 3 * ChannelCount;
68                 break;
69             default:
70                 FrameSize = 2 * ChannelCount;
71         }
72         TotalFrameCount = sfInfo.frames;
73 
74         Loops = 0;
75         LoopStart = 0;
76         LoopEnd = 0;
77         SF_INSTRUMENT instrument;
78         if (sf_command(pSndFile, SFC_GET_INSTRUMENT,
79                        &instrument, sizeof(instrument)) != SF_FALSE) {
80             // TODO: instrument.basenote
81 #if HAVE_SF_INSTRUMENT_LOOPS
82             if (instrument.loop_count && instrument.loops[0].mode != SF_LOOP_NONE) {
83                 Loops = 1;
84                 LoopStart = instrument.loops[0].start;
85                 LoopEnd = instrument.loops[0].end;
86             }
87 #endif
88         }
89         if(!DontClose) Close();
90 
91         if (FrameSize == 3 * ChannelCount && (
92 #if HAVE_DECL_SF_FORMAT_FLAC
93                 (Format & SF_FORMAT_TYPEMASK) == SF_FORMAT_FLAC ||
94 #endif
95                 (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT ||
96                 (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_32)) {
97             pConvertBuffer = new int[CONVERT_BUFFER_SIZE];
98         }
99     }
100 
~SampleFile()101     SampleFile::~SampleFile() {
102         Close();
103         ReleaseSampleData();
104         delete[] pConvertBuffer;
105     }
106 
Open()107     void SampleFile::Open() {
108         if(pSndFile) return; // Already opened
109         SF_INFO sfInfo;
110         sfInfo.format = 0;
111         pSndFile = sf_open(File.c_str(), SFM_READ, &sfInfo);
112         if(pSndFile == NULL) throw Exception(File + ": Can't load sample");
113         #if CONFIG_DEVMODE
114         std::cout << "Number of opened sample files: " << ++SampleFile_OpenFilesCount << std::endl;
115         #endif
116     }
117 
Close()118     void SampleFile::Close() {
119         if(pSndFile == NULL) return;
120         if(sf_close(pSndFile)) std::cerr << "Sample::Close() " << "Failed to close " << File << std::endl;
121         pSndFile = NULL;
122         #if CONFIG_DEVMODE
123         std::cout << "Number of opened sample files: " << --SampleFile_OpenFilesCount << std::endl;
124         #endif
125     }
126 
SetPos(unsigned long FrameOffset)127     long SampleFile::SetPos(unsigned long FrameOffset) {
128         return SetPos(FrameOffset, SEEK_SET);
129     }
130 
SetPos(unsigned long FrameCount,int Whence)131     long SampleFile::SetPos(unsigned long FrameCount, int Whence) {
132         if(pSndFile == NULL) {
133             std::cerr << "Sample::SetPos() " << File << " not opened" << std::endl;
134             return -1;
135         }
136 
137         return sf_seek(pSndFile, FrameCount, Whence);
138     }
139 
GetPos()140     long SampleFile::GetPos() {
141         if(pSndFile == NULL) {
142             std::cerr << "Sample::GetPos() " << File << " not opened" << std::endl;
143             return -1;
144         }
145 
146         return sf_seek(pSndFile, 0, SEEK_CUR);
147     }
148 
LoadSampleData()149     Sample::buffer_t SampleFile::LoadSampleData() {
150         return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), 0); // 0 amount of NullSamples
151     }
152 
LoadSampleData(unsigned long FrameCount)153     Sample::buffer_t SampleFile::LoadSampleData(unsigned long FrameCount) {
154         return LoadSampleDataWithNullSamplesExtension(FrameCount, 0); // 0 amount of NullSamples
155     }
156 
LoadSampleDataWithNullSamplesExtension(uint NullFrameCount)157     Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(uint NullFrameCount) {
158         return LoadSampleDataWithNullSamplesExtension(GetTotalFrameCount(), NullFrameCount);
159     }
160 
LoadSampleDataWithNullSamplesExtension(unsigned long FrameCount,uint NullFramesCount)161     Sample::buffer_t SampleFile::LoadSampleDataWithNullSamplesExtension(unsigned long FrameCount, uint NullFramesCount) {
162         Open();
163         if (FrameCount > GetTotalFrameCount()) FrameCount = GetTotalFrameCount();
164 
165         if (Offset > MaxOffset && FrameCount < GetTotalFrameCount()) {
166             FrameCount = FrameCount + Offset > GetTotalFrameCount() ? GetTotalFrameCount() - Offset : FrameCount;
167             // Offset the RAM cache
168             RAMCacheOffset = Offset;
169         }
170         if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
171         unsigned long allocationsize = (FrameCount + NullFramesCount) * this->FrameSize;
172         SetPos(RAMCacheOffset, SEEK_SET); // reset read position to playback start point
173         RAMCache.pStart            = new int8_t[allocationsize];
174 
175         RAMCache.Size = Read(RAMCache.pStart, FrameCount) * this->FrameSize;
176         RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
177         // fill the remaining buffer space with silence samples
178         memset((int8_t*)RAMCache.pStart + RAMCache.Size, 0, RAMCache.NullExtensionSize);
179         Close();
180         return GetCache();
181     }
182 
Read(void * pBuffer,unsigned long FrameCount)183     long SampleFile::Read(void* pBuffer, unsigned long FrameCount) {
184         Open();
185 
186         if (GetPos() + FrameCount > GetTotalFrameCount()) FrameCount = GetTotalFrameCount() - GetPos(); // For the cases where a different sample end is specified (not the end of the file)
187 
188         // ogg and flac files must be read with sf_readf, not
189         // sf_read_raw. On big endian machines, sf_readf_short is also
190         // used for 16 bit wav files, to get automatic endian
191         // conversion (for 24 bit samples this is handled in
192         // Synthesize::GetSample instead).
193 
194 #if WORDS_BIGENDIAN || HAVE_DECL_SF_FORMAT_VORBIS || HAVE_DECL_SF_FORMAT_FLAC
195         if (
196 #if WORDS_BIGENDIAN
197             FrameSize == 2 * ChannelCount
198 #else
199 #if HAVE_DECL_SF_FORMAT_VORBIS
200             ((Format & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS)
201 #if HAVE_DECL_SF_FORMAT_FLAC
202             ||
203 #endif
204 #endif
205 #if HAVE_DECL_SF_FORMAT_FLAC
206             (FrameSize == 2 * ChannelCount &&
207              (Format & SF_FORMAT_TYPEMASK) == SF_FORMAT_FLAC)
208 #endif
209 #endif
210             ) {
211             return sf_readf_short(pSndFile, static_cast<short*>(pBuffer), FrameCount);
212         } else if (FrameSize == 3 * ChannelCount && (
213 #if HAVE_DECL_SF_FORMAT_FLAC
214                        (Format & SF_FORMAT_TYPEMASK) == SF_FORMAT_FLAC ||
215 #endif
216                        (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT ||
217                        (Format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_32)) {
218             // 24 bit flac needs to be converted from the 32 bit
219             // integers returned by libsndfile. Float and 32 bit pcm
220             // are treated in the same way.
221             int j = 0;
222             sf_count_t count = FrameCount;
223             const sf_count_t bufsize = CONVERT_BUFFER_SIZE / ChannelCount;
224             unsigned char* const dst = static_cast<unsigned char*>(pBuffer);
225             while (count > 0) {
226                 int n = (int) sf_readf_int(pSndFile, pConvertBuffer, std::min(count, bufsize));
227                 if (n <= 0) break;
228                 for (int i = 0 ; i < n * ChannelCount ; i++) {
229                     dst[j++] = pConvertBuffer[i] >> 8;
230                     dst[j++] = pConvertBuffer[i] >> 16;
231                     dst[j++] = pConvertBuffer[i] >> 24;
232                 }
233                 count -= n;
234             }
235             return FrameCount - count;
236         } else
237 #endif
238         {
239             int bytes = (int)sf_read_raw(pSndFile, pBuffer, FrameCount * GetFrameSize());
240             return bytes / GetFrameSize();
241         }
242     }
243 
ReadAndLoop(void * pBuffer,unsigned long FrameCount,PlaybackState * pPlaybackState)244     unsigned long SampleFile::ReadAndLoop (
245         void*           pBuffer,
246         unsigned long   FrameCount,
247         PlaybackState*  pPlaybackState
248     ) {
249         // TODO:
250         SetPos(pPlaybackState->position);
251         unsigned long count = Read(pBuffer, FrameCount);
252         pPlaybackState->position = GetPos();
253         return count;
254     }
255 
ReleaseSampleData()256     void SampleFile::ReleaseSampleData() {
257         if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
258         RAMCache.pStart = NULL;
259         RAMCache.Size   = 0;
260         RAMCache.NullExtensionSize = 0;
261     }
262 
GetCache()263     Sample::buffer_t SampleFile::GetCache() {
264         // return a copy of the buffer_t structure
265         buffer_t result;
266         result.Size              = this->RAMCache.Size;
267         result.pStart            = this->RAMCache.pStart;
268         result.NullExtensionSize = this->RAMCache.NullExtensionSize;
269         return result;
270     }
271 } // namespace LinuxSampler
272