mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-12 23:44:19 +00:00
Implement and use a libsndfile decoder
This commit is contained in:
parent
5370a1cb46
commit
b38589e2dc
7 changed files with 514 additions and 42 deletions
29
FindSndFile.cmake
Normal file
29
FindSndFile.cmake
Normal file
|
@ -0,0 +1,29 @@
|
|||
# - Try to find SndFile
|
||||
# Once done this will define
|
||||
#
|
||||
# SNDFILE_FOUND - system has SndFile
|
||||
# SNDFILE_INCLUDE_DIRS - the SndFile include directory
|
||||
# SNDFILE_LIBRARIES - Link these to use SndFile
|
||||
#
|
||||
# Copyright © 2006 Wengo
|
||||
# Copyright © 2009 Guillaume Martres
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
find_path(SNDFILE_INCLUDE_DIR NAMES sndfile.h)
|
||||
|
||||
find_library(SNDFILE_LIBRARY NAMES sndfile sndfile-1)
|
||||
|
||||
set(SNDFILE_INCLUDE_DIRS ${SNDFILE_INCLUDE_DIR})
|
||||
set(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY})
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set SNDFILE_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SndFile DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR)
|
||||
|
||||
# show the SNDFILE_INCLUDE_DIRS and SNDFILE_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(SNDFILE_INCLUDE_DIRS SNDFILE_LIBRARIES)
|
|
@ -306,6 +306,10 @@ if( NO_OPENAL )
|
|||
add_definitions( -DNO_OPENAL=1 )
|
||||
endif( NO_OPENAL )
|
||||
|
||||
# Search for libSndFile
|
||||
|
||||
find_package( SndFile )
|
||||
|
||||
# Search for FluidSynth
|
||||
|
||||
find_package( FluidSynth )
|
||||
|
@ -556,6 +560,11 @@ message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
|
|||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" )
|
||||
include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" )
|
||||
|
||||
if( SNDFILE_FOUND )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SNDFILE_LIBRARIES}" )
|
||||
include_directories( "${SNDFILE_INCLUDE_DIRS}" )
|
||||
endif( SNDFILE_FOUND )
|
||||
|
||||
if( NOT DYN_FLUIDSYNTH)
|
||||
if( FLUIDSYNTH_FOUND )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" )
|
||||
|
@ -670,6 +679,9 @@ else( SSE_MATTERS )
|
|||
set( X86_SOURCES )
|
||||
endif( SSE_MATTERS )
|
||||
|
||||
if( SNDFILE_FOUND )
|
||||
add_definitions( -DHAVE_SNDFILE )
|
||||
endif( SNDFILE_FOUND )
|
||||
if( DYN_FLUIDSYNTH )
|
||||
add_definitions( -DHAVE_FLUIDSYNTH -DDYN_FLUIDSYNTH )
|
||||
elseif( FLUIDSYNTH_FOUND )
|
||||
|
@ -1033,6 +1045,7 @@ add_executable( zdoom WIN32
|
|||
resourcefiles/file_directory.cpp
|
||||
resourcefiles/resourcefile.cpp
|
||||
sfmt/SFMT.cpp
|
||||
sound/audio_sndfile_decoder.cpp
|
||||
sound/fmodsound.cpp
|
||||
sound/i_music.cpp
|
||||
sound/i_sound.cpp
|
||||
|
|
243
src/sound/audio_sndfile_decoder.cpp
Normal file
243
src/sound/audio_sndfile_decoder.cpp
Normal file
|
@ -0,0 +1,243 @@
|
|||
#include "i_soundinternal.h"
|
||||
|
||||
#ifdef HAVE_SNDFILE
|
||||
sf_count_t SndFileDecoder::file_get_filelen(void *user_data)
|
||||
{
|
||||
SndFileDecoder *self = reinterpret_cast<SndFileDecoder*>(user_data);
|
||||
return self->FileLength;
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::file_seek(sf_count_t offset, int whence, void *user_data)
|
||||
{
|
||||
SndFileDecoder *self = reinterpret_cast<SndFileDecoder*>(user_data);
|
||||
|
||||
long cur = ftell(self->File);
|
||||
if(cur < 0 || (unsigned long)cur < self->FileLength)
|
||||
return -1;
|
||||
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
if(offset < 0 || offset > (sf_count_t)self->FileLength)
|
||||
return -1;
|
||||
cur = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
cur -= self->FileOffset;
|
||||
if((offset > 0 && (sf_count_t)(self->FileLength-cur) < offset) ||
|
||||
(offset < 0 && (sf_count_t)cur < -offset))
|
||||
return -1;
|
||||
cur += offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if(offset > 0 || -offset > (sf_count_t)self->FileLength)
|
||||
return -1;
|
||||
cur = self->FileLength + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(fseek(self->File, cur + self->FileOffset, SEEK_SET) != 0)
|
||||
return -1;
|
||||
return cur;
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::file_read(void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
SndFileDecoder *self = reinterpret_cast<SndFileDecoder*>(user_data);
|
||||
|
||||
long cur = ftell(self->File);
|
||||
if(cur < 0 || (unsigned long)cur < self->FileLength)
|
||||
return -1;
|
||||
|
||||
cur -= self->FileOffset;
|
||||
if(count > (sf_count_t)(self->FileLength-cur))
|
||||
count = self->FileLength-cur;
|
||||
|
||||
return fread(ptr, 1, count, self->File);
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::file_write(const void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::file_tell(void *user_data)
|
||||
{
|
||||
SndFileDecoder *self = reinterpret_cast<SndFileDecoder*>(user_data);
|
||||
|
||||
long cur = ftell(self->File);
|
||||
if(cur < 0 || (unsigned long)cur < self->FileLength)
|
||||
return -1;
|
||||
return cur - self->FileOffset;
|
||||
}
|
||||
|
||||
|
||||
sf_count_t SndFileDecoder::mem_get_filelen(void *user_data)
|
||||
{
|
||||
SndFileDecoder *self = reinterpret_cast<SndFileDecoder*>(user_data);
|
||||
return self->MemLength;
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::mem_seek(sf_count_t offset, int whence, void *user_data)
|
||||
{
|
||||
SndFileDecoder *self = reinterpret_cast<SndFileDecoder*>(user_data);
|
||||
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
if(offset < 0 || offset > (sf_count_t)self->MemLength)
|
||||
return -1;
|
||||
self->MemPos = offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
if((offset > 0 && (sf_count_t)(self->MemLength-self->MemPos) < offset) ||
|
||||
(offset < 0 && (sf_count_t)self->MemPos < -offset))
|
||||
return -1;
|
||||
self->MemPos += offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if(offset > 0 || -offset > (sf_count_t)self->MemLength)
|
||||
return -1;
|
||||
self->MemPos = self->MemLength + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return self->MemPos;
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::mem_read(void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
SndFileDecoder *self = reinterpret_cast<SndFileDecoder*>(user_data);
|
||||
|
||||
if(count > (sf_count_t)(self->MemLength-self->MemPos))
|
||||
count = self->MemLength-self->MemPos;
|
||||
|
||||
memcpy(ptr, self->MemData+self->MemPos, count);
|
||||
self->MemPos += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::mem_write(const void *ptr, sf_count_t count, void *user_data)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sf_count_t SndFileDecoder::mem_tell(void *user_data)
|
||||
{
|
||||
SndFileDecoder *self = reinterpret_cast<SndFileDecoder*>(user_data);
|
||||
return self->MemPos;
|
||||
}
|
||||
|
||||
|
||||
SndFileDecoder::~SndFileDecoder()
|
||||
{
|
||||
if(SndFile)
|
||||
sf_close(SndFile);
|
||||
SndFile = 0;
|
||||
}
|
||||
|
||||
bool SndFileDecoder::open(const char *data, size_t length)
|
||||
{
|
||||
SF_VIRTUAL_IO sfio = { mem_get_filelen, mem_seek, mem_read, mem_write, mem_tell };
|
||||
|
||||
MemData = data;
|
||||
MemPos = 0;
|
||||
MemLength = length;
|
||||
SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this);
|
||||
if(SndFile)
|
||||
{
|
||||
if(SndInfo.channels != 1 && SndInfo.channels != 2)
|
||||
{
|
||||
sf_close(SndFile);
|
||||
SndFile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return SndFile != 0;
|
||||
}
|
||||
|
||||
bool SndFileDecoder::open(const char *fname, size_t offset, size_t length)
|
||||
{
|
||||
SF_VIRTUAL_IO sfio = { mem_get_filelen, mem_seek, mem_read, mem_write, mem_tell };
|
||||
|
||||
FileOffset = offset;
|
||||
FileLength = length;
|
||||
File = fopen(fname, "rb");
|
||||
if(File)
|
||||
{
|
||||
if(fseek(File, offset, SEEK_SET) == 0)
|
||||
{
|
||||
SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this);
|
||||
if(SndFile)
|
||||
{
|
||||
if(SndInfo.channels == 1 || SndInfo.channels == 2)
|
||||
return true;
|
||||
|
||||
sf_close(SndFile);
|
||||
SndFile = 0;
|
||||
}
|
||||
}
|
||||
fclose(File);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SndFileDecoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
|
||||
{
|
||||
*samplerate = SndInfo.samplerate;
|
||||
|
||||
if(SndInfo.channels == 2)
|
||||
*chans = ChannelConfig_Stereo;
|
||||
else
|
||||
*chans = ChannelConfig_Mono;
|
||||
|
||||
*type = SampleType_Int16;
|
||||
}
|
||||
|
||||
size_t SndFileDecoder::read(char *buffer, size_t bytes)
|
||||
{
|
||||
int framesize = 2 * SndInfo.channels;
|
||||
return sf_readf_short(SndFile, (short*)buffer, bytes/framesize) * framesize;
|
||||
}
|
||||
|
||||
std::vector<char> SndFileDecoder::readAll()
|
||||
{
|
||||
if(SndInfo.frames <= 0)
|
||||
return SoundDecoder::readAll();
|
||||
|
||||
int framesize = 2 * SndInfo.channels;
|
||||
std::vector<char> output;
|
||||
|
||||
output.resize(SndInfo.frames * framesize);
|
||||
size_t got = read(&output[0], output.size());
|
||||
output.resize(got);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
bool SndFileDecoder::seek(size_t ms_offset)
|
||||
{
|
||||
size_t smp_offset = (size_t)((double)ms_offset / 1000. * SndInfo.samplerate);
|
||||
if(sf_seek(SndFile, smp_offset, SEEK_SET) < 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t SndFileDecoder::getSampleOffset()
|
||||
{
|
||||
return sf_seek(SndFile, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -521,9 +521,32 @@ SoundHandle SoundRenderer::LoadSoundVoc(BYTE *sfxdata, int length)
|
|||
}
|
||||
|
||||
|
||||
SoundDecoder *SoundRenderer::CreateDecoder(BYTE *sfxdata, int length)
|
||||
SoundDecoder *SoundRenderer::CreateDecoder(const BYTE *sfxdata, int length)
|
||||
{
|
||||
return NULL;
|
||||
SoundDecoder *decoder = NULL;
|
||||
#ifdef HAVE_SNDFILE
|
||||
decoder = new SndFileDecoder;
|
||||
if(!decoder->open((const char*)sfxdata, length))
|
||||
{
|
||||
delete decoder;
|
||||
decoder = NULL;
|
||||
}
|
||||
#endif
|
||||
return decoder;
|
||||
}
|
||||
|
||||
SoundDecoder* SoundRenderer::CreateDecoder(const char *fname, int offset, int length)
|
||||
{
|
||||
SoundDecoder *decoder = NULL;
|
||||
#ifdef HAVE_SNDFILE
|
||||
decoder = new SndFileDecoder;
|
||||
if(!decoder->open(fname, offset, length))
|
||||
{
|
||||
delete decoder;
|
||||
decoder = NULL;
|
||||
}
|
||||
#endif
|
||||
return decoder;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -154,7 +154,8 @@ public:
|
|||
virtual void DrawWaveDebug(int mode);
|
||||
|
||||
protected:
|
||||
virtual SoundDecoder *CreateDecoder(BYTE *sfxdata, int length);
|
||||
virtual SoundDecoder *CreateDecoder(const BYTE *sfxdata, int length);
|
||||
virtual SoundDecoder *CreateDecoder(const char *fname, int offset, int length);
|
||||
};
|
||||
|
||||
extern SoundRenderer *GSnd;
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#define __SNDINT_H
|
||||
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "basictypes.h"
|
||||
#include "vectors.h"
|
||||
|
||||
// For convenience, this structure matches FMOD_REVERB_PROPERTIES.
|
||||
// Since I can't very well #include system-specific stuff in the
|
||||
|
@ -106,22 +108,16 @@ struct FISoundChannel
|
|||
enum SampleType
|
||||
{
|
||||
SampleType_UInt8,
|
||||
SampleType_Int16,
|
||||
SampleType_Float32
|
||||
SampleType_Int16
|
||||
};
|
||||
enum ChannelConfig
|
||||
{
|
||||
ChannelConfig_Mono,
|
||||
ChannelConfig_Stereo,
|
||||
ChannelConfig_Quad,
|
||||
ChannelConfig_5point1,
|
||||
ChannelConfig_7point1
|
||||
ChannelConfig_Stereo
|
||||
};
|
||||
|
||||
struct SoundDecoder
|
||||
{
|
||||
virtual bool open(const char *data, size_t length) = 0;
|
||||
|
||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type) = 0;
|
||||
|
||||
virtual size_t read(char *buffer, size_t bytes) = 0;
|
||||
|
@ -132,10 +128,61 @@ struct SoundDecoder
|
|||
SoundDecoder() { }
|
||||
virtual ~SoundDecoder() { }
|
||||
|
||||
protected:
|
||||
virtual bool open(const char *data, size_t length) = 0;
|
||||
virtual bool open(const char *fname, size_t offset, size_t length) = 0;
|
||||
friend class SoundRenderer;
|
||||
|
||||
private:
|
||||
// Make non-copyable
|
||||
SoundDecoder(const SoundDecoder &rhs);
|
||||
SoundDecoder& operator=(const SoundDecoder &rhs);
|
||||
};
|
||||
|
||||
#ifdef HAVE_SNDFILE
|
||||
#include "sndfile.h"
|
||||
struct SndFileDecoder : public SoundDecoder
|
||||
{
|
||||
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
|
||||
|
||||
virtual size_t read(char *buffer, size_t bytes);
|
||||
virtual std::vector<char> readAll();
|
||||
virtual bool seek(size_t ms_offset);
|
||||
virtual size_t getSampleOffset();
|
||||
|
||||
SndFileDecoder() : SndFile(0) { }
|
||||
virtual ~SndFileDecoder();
|
||||
|
||||
protected:
|
||||
virtual bool open(const char *data, size_t length);
|
||||
virtual bool open(const char *fname, size_t offset, size_t length);
|
||||
|
||||
private:
|
||||
SNDFILE *SndFile;
|
||||
SF_INFO SndInfo;
|
||||
|
||||
FILE *File;
|
||||
size_t FileLength;
|
||||
size_t FileOffset;
|
||||
static sf_count_t file_get_filelen(void *user_data);
|
||||
static sf_count_t file_seek(sf_count_t offset, int whence, void *user_data);
|
||||
static sf_count_t file_read(void *ptr, sf_count_t count, void *user_data);
|
||||
static sf_count_t file_write(const void *ptr, sf_count_t count, void *user_data);
|
||||
static sf_count_t file_tell(void *user_data);
|
||||
|
||||
const char *MemData;
|
||||
size_t MemLength;
|
||||
size_t MemPos;
|
||||
static sf_count_t mem_get_filelen(void *user_data);
|
||||
static sf_count_t mem_seek(sf_count_t offset, int whence, void *user_data);
|
||||
static sf_count_t mem_read(void *ptr, sf_count_t count, void *user_data);
|
||||
static sf_count_t mem_write(const void *ptr, sf_count_t count, void *user_data);
|
||||
static sf_count_t mem_tell(void *user_data);
|
||||
|
||||
// Make non-copyable
|
||||
SndFileDecoder(const SndFileDecoder &rhs);
|
||||
SndFileDecoder& operator=(const SndFileDecoder &rhs);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -212,6 +212,28 @@ class OpenALCallbackStream : public SoundStream
|
|||
ALuint Source;
|
||||
|
||||
bool Playing;
|
||||
bool Looping;
|
||||
ALfloat Volume;
|
||||
|
||||
|
||||
std::vector<BYTE> DecoderData;
|
||||
std::auto_ptr<SoundDecoder> Decoder;
|
||||
static bool DecoderCallback(SoundStream *_sstream, void *ptr, int length, void *user)
|
||||
{
|
||||
OpenALCallbackStream *self = static_cast<OpenALCallbackStream*>(_sstream);
|
||||
if(length < 0) return false;
|
||||
|
||||
size_t got = self->Decoder->read((char*)ptr, length);
|
||||
if(got < (unsigned int)length)
|
||||
{
|
||||
if(!self->Looping || !self->Decoder->seek(0))
|
||||
return false;
|
||||
got += self->Decoder->read((char*)ptr+got, length-got);
|
||||
}
|
||||
|
||||
return (got == (unsigned int)length);
|
||||
}
|
||||
|
||||
|
||||
bool SetupSource()
|
||||
{
|
||||
|
@ -251,10 +273,8 @@ class OpenALCallbackStream : public SoundStream
|
|||
}
|
||||
|
||||
public:
|
||||
ALfloat Volume;
|
||||
|
||||
OpenALCallbackStream(OpenALSoundRenderer *renderer)
|
||||
: Renderer(renderer), Source(0), Playing(false), Volume(1.0f)
|
||||
: Renderer(renderer), Source(0), Playing(false), Looping(false), Volume(1.0f)
|
||||
{
|
||||
Renderer->Streams.push_back(this);
|
||||
memset(Buffers, 0, sizeof(Buffers));
|
||||
|
@ -479,6 +499,89 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Init(const char *fname, int offset, int length, bool loop)
|
||||
{
|
||||
if(!SetupSource())
|
||||
return false;
|
||||
|
||||
Decoder.reset(Renderer->CreateDecoder(fname, offset, length));
|
||||
if(!Decoder.get()) return false;
|
||||
|
||||
Callback = DecoderCallback;
|
||||
UserData = NULL;
|
||||
Format = AL_NONE;
|
||||
|
||||
ChannelConfig chans;
|
||||
SampleType type;
|
||||
int srate;
|
||||
|
||||
Decoder->getInfo(&srate, &chans, &type);
|
||||
if(chans == ChannelConfig_Mono)
|
||||
{
|
||||
if(type == SampleType_UInt8) Format = AL_FORMAT_MONO8;
|
||||
if(type == SampleType_Int16) Format = AL_FORMAT_MONO16;
|
||||
}
|
||||
if(chans == ChannelConfig_Stereo)
|
||||
{
|
||||
if(type == SampleType_UInt8) Format = AL_FORMAT_STEREO8;
|
||||
if(type == SampleType_Int16) Format = AL_FORMAT_STEREO16;
|
||||
}
|
||||
|
||||
if(Format == AL_NONE)
|
||||
{
|
||||
Printf("Unsupported audio format (0x%x / 0x%x)\n", chans, type);
|
||||
return false;
|
||||
}
|
||||
SampleRate = srate;
|
||||
Looping = loop;
|
||||
|
||||
Data.resize((size_t)(0.2 * SampleRate) * 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Init(const BYTE *data, int length, bool loop)
|
||||
{
|
||||
if(!SetupSource())
|
||||
return false;
|
||||
|
||||
DecoderData.insert(DecoderData.end(), data, data+length);
|
||||
Decoder.reset(Renderer->CreateDecoder(&DecoderData[0], DecoderData.size()));
|
||||
if(!Decoder.get()) return false;
|
||||
|
||||
Callback = DecoderCallback;
|
||||
UserData = NULL;
|
||||
Format = AL_NONE;
|
||||
|
||||
ChannelConfig chans;
|
||||
SampleType type;
|
||||
int srate;
|
||||
|
||||
Decoder->getInfo(&srate, &chans, &type);
|
||||
if(chans == ChannelConfig_Mono)
|
||||
{
|
||||
if(type == SampleType_UInt8) Format = AL_FORMAT_MONO8;
|
||||
if(type == SampleType_Int16) Format = AL_FORMAT_MONO16;
|
||||
}
|
||||
if(chans == ChannelConfig_Stereo)
|
||||
{
|
||||
if(type == SampleType_UInt8) Format = AL_FORMAT_STEREO8;
|
||||
if(type == SampleType_Int16) Format = AL_FORMAT_STEREO16;
|
||||
}
|
||||
|
||||
if(Format == AL_NONE)
|
||||
{
|
||||
Printf("Unsupported audio format (0x%x / 0x%x)\n", chans, type);
|
||||
return false;
|
||||
}
|
||||
SampleRate = srate;
|
||||
Looping = loop;
|
||||
|
||||
Data.resize((size_t)(0.2 * SampleRate) * 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -955,21 +1058,37 @@ SoundHandle OpenALSoundRenderer::LoadSoundRaw(BYTE *sfxdata, int length, int fre
|
|||
SoundHandle OpenALSoundRenderer::LoadSound(BYTE *sfxdata, int length)
|
||||
{
|
||||
SoundHandle retval = { NULL };
|
||||
ALenum format;
|
||||
ALuint srate;
|
||||
ALenum format = AL_NONE;
|
||||
ChannelConfig chans;
|
||||
SampleType type;
|
||||
int srate;
|
||||
|
||||
Decoder decoder(sfxdata, length);
|
||||
if(!decoder.GetFormat(&format, &srate))
|
||||
return retval;
|
||||
std::auto_ptr<SoundDecoder> decoder(CreateDecoder(sfxdata, length));
|
||||
if(!decoder.get()) return retval;
|
||||
|
||||
ALsizei size;
|
||||
void *data = decoder.GetData(&size);
|
||||
if(data == NULL)
|
||||
decoder->getInfo(&srate, &chans, &type);
|
||||
if(chans == ChannelConfig_Mono)
|
||||
{
|
||||
if(type == SampleType_UInt8) format = AL_FORMAT_MONO8;
|
||||
if(type == SampleType_Int16) format = AL_FORMAT_MONO16;
|
||||
}
|
||||
if(chans == ChannelConfig_Stereo)
|
||||
{
|
||||
if(type == SampleType_UInt8) format = AL_FORMAT_STEREO8;
|
||||
if(type == SampleType_Int16) format = AL_FORMAT_STEREO16;
|
||||
}
|
||||
|
||||
if(format == AL_NONE)
|
||||
{
|
||||
Printf("Unsupported audio format (0x%x / 0x%x)\n", chans, type);
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::vector<char> data = decoder->readAll();
|
||||
|
||||
ALuint buffer = 0;
|
||||
alGenBuffers(1, &buffer);
|
||||
alBufferData(buffer, format, data, size, srate);
|
||||
alBufferData(buffer, format, &data[0], data.size(), srate);
|
||||
|
||||
ALenum err;
|
||||
if((err=getALError()) != AL_NO_ERROR)
|
||||
|
@ -1012,29 +1131,25 @@ void OpenALSoundRenderer::UnloadSound(SoundHandle sfx)
|
|||
delete ((ALuint*)sfx.data);
|
||||
}
|
||||
|
||||
short *OpenALSoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType type)
|
||||
short *OpenALSoundRenderer::DecodeSample(int outlen, const void *coded, int sizebytes, ECodecType ctype)
|
||||
{
|
||||
short *samples = (short*)malloc(outlen);
|
||||
memset(samples, 0, outlen);
|
||||
char *samples = (char*)calloc(1, outlen);
|
||||
ChannelConfig chans;
|
||||
SampleType type;
|
||||
int srate;
|
||||
|
||||
Decoder decoder(coded, sizebytes);
|
||||
ALenum format;
|
||||
ALuint srate;
|
||||
std::auto_ptr<SoundDecoder> decoder(CreateDecoder((const BYTE*)coded, sizebytes));
|
||||
if(!decoder.get()) return (short*)samples;
|
||||
|
||||
if(!decoder.GetFormat(&format, &srate))
|
||||
return samples;
|
||||
if(format != AL_FORMAT_MONO16)
|
||||
decoder->getInfo(&srate, &chans, &type);
|
||||
if(chans != ChannelConfig_Mono || type != SampleType_Int16)
|
||||
{
|
||||
DPrintf("Sample is not 16-bit mono\n");
|
||||
return samples;
|
||||
return (short*)samples;
|
||||
}
|
||||
|
||||
ALsizei size;
|
||||
void *data = decoder.GetData(&size);
|
||||
if(data != NULL)
|
||||
memcpy(samples, data, std::min<size_t>(size, outlen));
|
||||
|
||||
return samples;
|
||||
decoder->read(samples, outlen);
|
||||
return (short*)samples;
|
||||
}
|
||||
|
||||
SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata)
|
||||
|
@ -1047,10 +1162,11 @@ SoundStream *OpenALSoundRenderer::CreateStream(SoundStreamCallback callback, int
|
|||
|
||||
SoundStream *OpenALSoundRenderer::OpenStream(const char *filename, int flags, int offset, int length)
|
||||
{
|
||||
std::auto_ptr<OpenALSoundStream> stream(new OpenALSoundStream(this));
|
||||
std::auto_ptr<OpenALCallbackStream> stream(new OpenALCallbackStream(this));
|
||||
|
||||
bool ok = ((offset == -1) ? stream->Init((const BYTE*)filename, length) :
|
||||
stream->Init(filename, offset, length));
|
||||
bool loop = (flags&SoundStream::Loop);
|
||||
bool ok = ((offset == -1) ? stream->Init((const BYTE*)filename, length, loop) :
|
||||
stream->Init(filename, offset, length, loop));
|
||||
if(ok == false)
|
||||
return NULL;
|
||||
|
||||
|
|
Loading…
Reference in a new issue