@@ -111,31 +111,19 @@ struct SoundBuffer
std::vector<char > buffer;
};
SoundBuffer* loadOggFile (const std::string &filepath)
SoundBuffer *load_opened_ogg_file (OggVorbis_File *oggFile,
const std::string &filename_for_logging)
{
int endian = 0 ; // 0 for Little-Endian, 1 for Big-Endian
int bitStream;
long bytes;
char array[BUFFER_SIZE]; // Local fixed size array
vorbis_info *pInfo;
OggVorbis_File oggFile;
// Do a dumb-ass static string copy for old versions of ov_fopen
// because they expect a non-const char*
char nonconst[10000 ];
snprintf (nonconst, 10000 , " %s" , filepath.c_str ());
// Try opening the given file
// if(ov_fopen(filepath.c_str(), &oggFile) != 0)
if (ov_fopen (nonconst, &oggFile) != 0 )
{
infostream<<" Audio: Error opening " <<filepath<<" for decoding" <<std::endl;
return NULL ;
}
SoundBuffer *snd = new SoundBuffer;
// Get some information about the OGG file
pInfo = ov_info (& oggFile, -1 );
pInfo = ov_info (oggFile, -1 );
// Check the number of channels... always use 16-bit samples
if (pInfo->channels == 1 )
@@ -150,12 +138,13 @@ SoundBuffer* loadOggFile(const std::string &filepath)
do
{
// Read up to a buffer's worth of decoded sound data
bytes = ov_read (& oggFile, array, BUFFER_SIZE, endian, 2 , 1 , &bitStream);
bytes = ov_read (oggFile, array, BUFFER_SIZE, endian, 2 , 1 , &bitStream);
if (bytes < 0 )
{
ov_clear (&oggFile);
infostream<<" Audio: Error decoding " <<filepath<<std::endl;
ov_clear (oggFile);
infostream << " Audio: Error decoding "
<< filename_for_logging << std::endl;
return NULL ;
}
@@ -175,14 +164,100 @@ SoundBuffer* loadOggFile(const std::string &filepath)
<<" preparing sound buffer" <<std::endl;
}
infostream<<" Audio file " <<filepath<<" loaded" <<std::endl;
infostream << " Audio file "
<< filename_for_logging << " loaded" << std::endl;
// Clean up!
ov_clear (& oggFile);
ov_clear (oggFile);
return snd;
}
SoundBuffer *load_ogg_from_file (const std::string &path)
{
OggVorbis_File oggFile;
// Try opening the given file.
// This requires libvorbis >= 1.3.2, as
// previous versions expect a non-const char *
if (ov_fopen (path.c_str (), &oggFile) != 0 ) {
infostream << " Audio: Error opening " << path
<< " for decoding" << std::endl;
return NULL ;
}
return load_opened_ogg_file (&oggFile, path);
}
struct BufferSource {
const char *buf;
size_t cur_offset;
size_t len;
};
size_t buffer_sound_read_func (void *ptr, size_t size, size_t nmemb, void *datasource)
{
BufferSource *s = (BufferSource *)datasource;
size_t copied_size = MYMIN (s->len - s->cur_offset , size);
memcpy (ptr, s->buf + s->cur_offset , copied_size);
s->cur_offset += copied_size;
return copied_size;
}
int buffer_sound_seek_func (void *datasource, ogg_int64_t offset, int whence)
{
BufferSource *s = (BufferSource *)datasource;
if (whence == SEEK_SET) {
if (offset < 0 || (size_t )MYMAX (offset, 0 ) >= s->len ) {
// offset out of bounds
return -1 ;
}
s->cur_offset = offset;
return 0 ;
} else if (whence == SEEK_CUR) {
if ((size_t )MYMIN (-offset, 0 ) > s->cur_offset
|| s->cur_offset + offset > s->len ) {
// offset out of bounds
return -1 ;
}
s->cur_offset += offset;
return 0 ;
}
// invalid whence param (SEEK_END doesn't have to be supported)
return -1 ;
}
long BufferSourceell_func (void *datasource)
{
BufferSource *s = (BufferSource *)datasource;
return s->cur_offset ;
}
static ov_callbacks g_buffer_ov_callbacks = {
&buffer_sound_read_func,
&buffer_sound_seek_func,
NULL ,
&BufferSourceell_func
};
SoundBuffer *load_ogg_from_buffer (const std::string &buf, const std::string &id_for_log)
{
OggVorbis_File oggFile;
BufferSource s;
s.buf = buf.c_str ();
s.cur_offset = 0 ;
s.len = buf.size ();
if (ov_open_callbacks (&s, &oggFile, NULL , 0 , g_buffer_ov_callbacks) != 0 ) {
infostream << " Audio: Error opening " << id_for_log
<< " for decoding" << std::endl;
return NULL ;
}
return load_opened_ogg_file (&oggFile, id_for_log);
}
struct PlayingSound
{
ALuint source_id;
@@ -211,7 +286,7 @@ class OpenALSoundManager: public ISoundManager
m_is_initialized (false )
{
ALCenum error = ALC_NO_ERROR;
infostream<<" Audio: Initializing..." <<std::endl;
m_device = alcOpenDevice (NULL );
@@ -283,7 +358,7 @@ class OpenALSoundManager: public ISoundManager
m_buffers.clear ();
infostream<<" Audio: Deinitialized." <<std::endl;
}
void addBuffer (const std::string &name, SoundBuffer *buf)
{
std::map<std::string, std::vector<SoundBuffer*> >::iterator i =
@@ -375,15 +450,15 @@ class OpenALSoundManager: public ISoundManager
m_sounds_playing[id] = sound;
return id;
}
void deleteSound (int id)
{
std::map<int , PlayingSound*>::iterator i =
m_sounds_playing.find (id);
if (i == m_sounds_playing.end ())
return ;
PlayingSound *sound = i->second ;
alDeleteSources (1 , &sound->source_id );
delete sound;
@@ -411,7 +486,7 @@ class OpenALSoundManager: public ISoundManager
}
return getBuffer (name);
}
// Remove stopped sounds
void maintain ()
{
@@ -449,26 +524,18 @@ class OpenALSoundManager: public ISoundManager
bool loadSoundFile (const std::string &name,
const std::string &filepath)
{
SoundBuffer *buf = loadOggFile (filepath);
if (buf)
SoundBuffer *buf = load_ogg_from_file (filepath);
if (buf)
addBuffer (name, buf);
return false ;
}
bool loadSoundData (const std::string &name,
const std::string &filedata)
{
// The vorbis API sucks; just write it to a file and use vorbisfile
// TODO: Actually load it directly from memory
std::string basepath = porting::path_user + DIR_DELIM + " cache" +
DIR_DELIM + " tmp" ;
std::string path = basepath + DIR_DELIM + " tmp.ogg" ;
verbosestream<<" OpenALSoundManager::loadSoundData(): Writing "
<<" temporary file to [" <<path<<" ]" <<std::endl;
fs::CreateAllDirs (basepath);
std::ofstream of (path.c_str (), std::ios::binary);
of.write (filedata.c_str (), filedata.size ());
of.close ();
return loadSoundFile (name, path);
SoundBuffer *buf = load_ogg_from_buffer (filedata, name);
if (buf)
addBuffer (name, buf);
return false ;
}
void updateListener (v3f pos, v3f vel, v3f at, v3f up)
@@ -482,7 +549,7 @@ class OpenALSoundManager: public ISoundManager
alListenerfv (AL_ORIENTATION, f);
warn_if_error (alGetError (), " updateListener" );
}
void setListenerGain (float gain)
{
alListenerf (AL_GAIN, gain);