SoundFileDefault.cpp
1 //
3 // SFML - Simple and Fast Multimedia Library
4 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 // you must not claim that you wrote the original software.
15 // If you use this software in a product, an acknowledgment
16 // in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 // and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
24 
26 // Headers
28 #include <SFML/Audio/SoundFileDefault.hpp>
29 #include <iostream>
30 #include <string.h>
31 
32 
33 namespace sf
34 {
35 namespace priv
36 {
40 SoundFileDefault::SoundFileDefault() :
41 myFile(NULL)
42 {
43 
44 }
45 
46 
50 SoundFileDefault::~SoundFileDefault()
51 {
52  if (myFile)
53  sf_close(myFile);
54 }
55 
56 
60 bool SoundFileDefault::IsFileSupported(const std::string& Filename, bool Read)
61 {
62  if (Read)
63  {
64  // Open the sound file
65  SF_INFO FileInfos;
66  SNDFILE* File = sf_open(Filename.c_str(), SFM_READ, &FileInfos);
67 
68  if (File)
69  {
70  sf_close(File);
71  return true;
72  }
73  else
74  {
75  return false;
76  }
77  }
78  else
79  {
80  // Check the extension
81  return GetFormatFromFilename(Filename) != -1;
82  }
83 }
84 
85 
89 bool SoundFileDefault::IsFileSupported(const char* Data, std::size_t SizeInBytes)
90 {
91  // Define the I/O custom functions for reading from memory
92  SF_VIRTUAL_IO VirtualIO;
93  VirtualIO.get_filelen = &SoundFileDefault::MemoryGetLength;
94  VirtualIO.read = &SoundFileDefault::MemoryRead;
95  VirtualIO.seek = &SoundFileDefault::MemorySeek;
96  VirtualIO.tell = &SoundFileDefault::MemoryTell;
97  VirtualIO.write = &SoundFileDefault::MemoryWrite;
98 
99  // Initialize the memory data
100  MemoryInfos Memory;
101  Memory.DataStart = Data;
102  Memory.DataPtr = Data;
103  Memory.TotalSize = SizeInBytes;
104 
105  // Open the sound file
106  SF_INFO FileInfos;
107  SNDFILE* File = sf_open_virtual(&VirtualIO, SFM_READ, &FileInfos, &Memory);
108 
109  if (File)
110  {
111  sf_close(File);
112  return true;
113  }
114  else
115  {
116  return false;
117  }
118 }
119 
120 
124 bool SoundFileDefault::OpenRead(const std::string& Filename, std::size_t& NbSamples, unsigned int& ChannelsCount, unsigned int& SampleRate)
125 {
126  // If the file is already opened, first close it
127  if (myFile)
128  sf_close(myFile);
129 
130  // Open the sound file
131  SF_INFO FileInfos;
132  myFile = sf_open(Filename.c_str(), SFM_READ, &FileInfos);
133  if (!myFile)
134  {
135  std::cerr << "Failed to read sound file \"" << Filename << "\"" << std::endl;
136  return false;
137  }
138 
139  // Set the sound parameters
140  ChannelsCount = FileInfos.channels;
141  SampleRate = FileInfos.samplerate;
142  NbSamples = static_cast<std::size_t>(FileInfos.frames) * ChannelsCount;
143 
144  return true;
145 }
146 
147 
151 bool SoundFileDefault::OpenRead(const char* Data, std::size_t SizeInBytes, std::size_t& NbSamples, unsigned int& ChannelsCount, unsigned int& SampleRate)
152 {
153  // If the file is already opened, first close it
154  if (myFile)
155  sf_close(myFile);
156 
157  // Define the I/O custom functions for reading from memory
158  SF_VIRTUAL_IO VirtualIO;
159  VirtualIO.get_filelen = &SoundFileDefault::MemoryGetLength;
160  VirtualIO.read = &SoundFileDefault::MemoryRead;
161  VirtualIO.seek = &SoundFileDefault::MemorySeek;
162  VirtualIO.tell = &SoundFileDefault::MemoryTell;
163  VirtualIO.write = &SoundFileDefault::MemoryWrite;
164 
165  // Initialize the memory data
166  myMemory.DataStart = Data;
167  myMemory.DataPtr = Data;
168  myMemory.TotalSize = SizeInBytes;
169 
170  // Open the sound file
171  SF_INFO FileInfos;
172  myFile = sf_open_virtual(&VirtualIO, SFM_READ, &FileInfos, &myMemory);
173  if (!myFile)
174  {
175  std::cerr << "Failed to read sound file from memory" << std::endl;
176  return false;
177  }
178 
179  // Set the sound parameters
180  ChannelsCount = FileInfos.channels;
181  SampleRate = FileInfos.samplerate;
182  NbSamples = static_cast<std::size_t>(FileInfos.frames) * ChannelsCount;
183 
184  return true;
185 }
186 
187 
191 bool SoundFileDefault::OpenWrite(const std::string& Filename, unsigned int ChannelsCount, unsigned int SampleRate)
192 {
193  // If the file is already opened, first close it
194  if (myFile)
195  sf_close(myFile);
196 
197  // Find the right format according to the file extension
198  int Format = GetFormatFromFilename(Filename);
199  if (Format == -1)
200  {
201  // Error : unrecognized extension
202  std::cerr << "Failed to create sound file \"" << Filename << "\" : unknown format" << std::endl;
203  return false;
204  }
205 
206  // Fill the sound infos with parameters
207  SF_INFO FileInfos;
208  FileInfos.channels = ChannelsCount;
209  FileInfos.samplerate = SampleRate;
210  FileInfos.format = Format | SF_FORMAT_PCM_16;
211 
212  // Open the sound file for writing
213  myFile = sf_open(Filename.c_str(), SFM_WRITE, &FileInfos);
214  if (!myFile)
215  {
216  std::cerr << "Failed to create sound file \"" << Filename << "\"" << std::endl;
217  return false;
218  }
219 
220  return true;
221 }
222 
223 
227 std::size_t SoundFileDefault::Read(Int16* Data, std::size_t NbSamples)
228 {
229  if (myFile && Data && NbSamples)
230  return static_cast<std::size_t>(sf_read_short(myFile, Data, NbSamples));
231  else
232  return 0;
233 }
234 
235 
239 void SoundFileDefault::Write(const Int16* Data, std::size_t NbSamples)
240 {
241  if (myFile && Data && NbSamples)
242  sf_write_short(myFile, Data, NbSamples);
243 }
244 
245 
250 int SoundFileDefault::GetFormatFromFilename(const std::string& Filename)
251 {
252  // Extract the extension
253  std::string Ext = "wav";
254  std::string::size_type Pos = Filename.find_last_of(".");
255  if (Pos != std::string::npos)
256  Ext = Filename.substr(Pos + 1);
257 
258  // Match every supported extension with its format constant
259  if (Ext == "wav" || Ext == "WAV" ) return SF_FORMAT_WAV;
260  if (Ext == "aif" || Ext == "AIF" ) return SF_FORMAT_AIFF;
261  if (Ext == "aiff" || Ext == "AIFF") return SF_FORMAT_AIFF;
262  if (Ext == "au" || Ext == "AU" ) return SF_FORMAT_AU;
263  if (Ext == "raw" || Ext == "RAW" ) return SF_FORMAT_RAW;
264  if (Ext == "paf" || Ext == "PAF" ) return SF_FORMAT_PAF;
265  if (Ext == "svx" || Ext == "SVX" ) return SF_FORMAT_SVX;
266  if (Ext == "voc" || Ext == "VOC" ) return SF_FORMAT_VOC;
267  if (Ext == "sf" || Ext == "SF" ) return SF_FORMAT_IRCAM;
268  if (Ext == "w64" || Ext == "W64" ) return SF_FORMAT_W64;
269  if (Ext == "mat4" || Ext == "MAT4") return SF_FORMAT_MAT4;
270  if (Ext == "mat5" || Ext == "MAT5") return SF_FORMAT_MAT5;
271  if (Ext == "pvf" || Ext == "PVF" ) return SF_FORMAT_PVF;
272  if (Ext == "htk" || Ext == "HTK" ) return SF_FORMAT_HTK;
273  if (Ext == "caf" || Ext == "CAF" ) return SF_FORMAT_CAF;
274  if (Ext == "nist" || Ext == "NIST") return SF_FORMAT_NIST; // SUPPORTED ?
275  if (Ext == "sds" || Ext == "SDS" ) return SF_FORMAT_SDS; // SUPPORTED ?
276  if (Ext == "avr" || Ext == "AVR" ) return SF_FORMAT_AVR; // SUPPORTED ?
277  if (Ext == "sd2" || Ext == "SD2" ) return SF_FORMAT_SD2; // SUPPORTED ?
278  if (Ext == "flac" || Ext == "FLAC") return SF_FORMAT_FLAC; // SUPPORTED ?
279 
280  return -1;
281 }
282 
283 
288 sf_count_t SoundFileDefault::MemoryGetLength(void* UserData)
289 {
290  MemoryInfos* Memory = static_cast<MemoryInfos*>(UserData);
291 
292  return Memory->TotalSize;
293 }
294 sf_count_t SoundFileDefault::MemoryRead(void* Ptr, sf_count_t Count, void* UserData)
295 {
296  MemoryInfos* Memory = static_cast<MemoryInfos*>(UserData);
297 
298  sf_count_t Position = Memory->DataPtr - Memory->DataStart;
299  if (Position + Count >= Memory->TotalSize)
300  Count = Memory->TotalSize - Position;
301 
302  memcpy(Ptr, Memory->DataPtr, static_cast<std::size_t>(Count));
303 
304  Memory->DataPtr += Count;
305 
306  return Count;
307 }
308 sf_count_t SoundFileDefault::MemorySeek(sf_count_t Offset, int Whence, void* UserData)
309 {
310  MemoryInfos* Memory = static_cast<MemoryInfos*>(UserData);
311 
312  sf_count_t Position = 0;
313  switch (Whence)
314  {
315  case SEEK_SET :
316  Position = Offset;
317  break;
318  case SEEK_CUR :
319  Position = Memory->DataPtr - Memory->DataStart + Offset;
320  break;
321  case SEEK_END :
322  Position = Memory->TotalSize - Offset;
323  break;
324  default :
325  Position = 0;
326  break;
327  }
328 
329  if (Position >= Memory->TotalSize)
330  Position = Memory->TotalSize - 1;
331  else if (Position < 0)
332  Position = 0;
333 
334  Memory->DataPtr = Memory->DataStart + Position;
335 
336  return Position;
337 }
338 sf_count_t SoundFileDefault::MemoryTell(void* UserData)
339 {
340  MemoryInfos* Memory = static_cast<MemoryInfos*>(UserData);
341 
342  return Memory->DataPtr - Memory->DataStart;
343 }
344 sf_count_t SoundFileDefault::MemoryWrite(const void*, sf_count_t, void*)
345 {
346  return 0;
347 }
348 
349 
350 } // namespace priv
351 
352 } // namespace sf