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