SoundFileDefault.cpp
1
2//
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
33namespace sf
34{
35namespace priv
36{
40SoundFileDefault::SoundFileDefault() :
41myFile(NULL)
42{
43
44}
45
46
50SoundFileDefault::~SoundFileDefault()
51{
52 if (myFile)
53 sf_close(myFile);
54}
55
56
60bool 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
89bool 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
124bool 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
151bool 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
191bool 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
227std::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
239void 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
250int 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
288sf_count_t SoundFileDefault::MemoryGetLength(void* UserData)
289{
290 MemoryInfos* Memory = static_cast<MemoryInfos*>(UserData);
291
292 return Memory->TotalSize;
293}
294sf_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}
308sf_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}
338sf_count_t SoundFileDefault::MemoryTell(void* UserData)
339{
340 MemoryInfos* Memory = static_cast<MemoryInfos*>(UserData);
341
342 return Memory->DataPtr - Memory->DataStart;
343}
344sf_count_t SoundFileDefault::MemoryWrite(const void*, sf_count_t, void*)
345{
346 return 0;
347}
348
349
350} // namespace priv
351
352} // namespace sf