📄 soundprovider_wave.cpp
字号:
/* $Id: soundprovider_wave.cpp,v 1.4 2003/08/21 22:58:00 mbn Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**
File purpose:
Simple sample support.
*/
#include "Sound/precomp.h"
#include "API/Sound/SoundProviders/soundprovider_wave.h"
#include "API/Core/IOData/inputsource_provider.h"
#include "API/Core/IOData/inputsource.h"
#include "API/Core/System/clanstring.h"
#include "API/Core/System/log.h"
#include "soundprovider_wave_generic.h"
#include "soundprovider_wave_session.h"
/////////////////////////////////////////////////////////////////////////////
// CL_SoundProvider_Wave construction:
CL_SoundProvider_Wave::CL_SoundProvider_Wave(
const std::string &filename,
CL_InputSourceProvider *provider,
bool stream) : impl(new CL_SoundProvider_Wave_Generic)
{
if (provider == 0) provider = CL_InputSourceProvider::create_file_provider(".");
else provider = provider->clone();
impl->provider = provider;
impl->filename = filename;
impl->stream = stream;
CL_InputSource *source = provider->open_source(filename);
// Check to see if this is really a .wav-file
char temp[12];
source->read(temp, 4);
source->seek(4, CL_InputSource::seek_cur);
source->read(&temp[4], 8);
source->seek(4, CL_InputSource::seek_cur);
if (memcmp(temp, "RIFFWAVEfmt ", 12) != 0)
{
delete impl;
throw CL_Error("Invalid RIFF WAVE header!");
}
CL_SoundProvider_Wave_Generic::WAVE_FORMAT format;
format.formatTag = source->read_short16();
format.nChannels = source->read_ushort16();
format.nSamplesPerSec = source->read_uint32();
format.nAvgBytesPerSec = source->read_uint32();
format.nBlockAlign = source->read_ushort16();
// FIXME: find a better way to handle format struct padding
source->read(temp, 2);
// Another sanity check
source->read(temp, 4);
temp[4] = 0;
if (memcmp(temp, "data", 4) != 0)
{
delete impl;
throw CL_Error("Invalid RIFF data chunk!");
}
int data_size = source->read_uint32();
int bytes_per_sample = format.nAvgBytesPerSec / format.nSamplesPerSec;
impl->frequency = format.nSamplesPerSec;
impl->num_channels = format.nChannels;
impl->num_samples = data_size / bytes_per_sample;
if (bytes_per_sample / format.nChannels == 2) impl->format = sf_16bit_signed;
else if (bytes_per_sample / format.nChannels == 1) impl->format = sf_8bit_signed;
else
{
delete impl;
throw CL_Error(
CL_String::format(
"Unsupported wave file format (channels=%1, bytes per sample=%2)",
format.nChannels,
bytes_per_sample));
}
impl->data = new char[data_size];
source->read(impl->data, data_size);
// 8 bit wave is unsigned, while 16 bit wave is signed!
if (impl->format == sf_8bit_signed)
{
for (int i=0; i<data_size; i++)
((unsigned char *) impl->data)[i] -= 128;
}
delete source;
}
CL_SoundProvider_Wave::~CL_SoundProvider_Wave()
{
delete[] impl->data;
delete impl->provider;
delete impl;
}
/////////////////////////////////////////////////////////////////////////////
// CL_SoundProvider_Wave operations:
CL_SoundProvider_Session *CL_SoundProvider_Wave::begin_session()
{
return new CL_SoundProvider_Wave_Session(impl);
}
void CL_SoundProvider_Wave::end_session(CL_SoundProvider_Session *session)
{
delete session;
}
/////////////////////////////////////////////////////////////////////////////
// CL_SoundProvider_Wave implementation:
/*
#ifdef WIN32
#pragma warning (disable:4786)
#endif
#include "API/Core/IOData/cl_endian.h"
#include "API/Core/IOData/inputsource_provider.h"
#include "API/Core/IOData/inputsource.h"
#include "API/Core/System/cl_assert.h"
#include "API/Core/System/error.h"
#include "API/Sound/SoundProviders/static_provider_raw.h"
#include "API/Sound/SoundProviders/static_provider_wave.h"
CL_SoundBuffer *CL_Sample::create(const std::string &sample_id, CL_InputSourceProvider *provider)
{
return new CL_SoundBuffer(new CL_Sample(sample_id, provider), true);
}
CL_Sample::CL_Sample(const std::string &s_id, CL_InputSourceProvider *_provider) : sample_id(s_id)
{
if (_provider == NULL)
{
provider = CL_InputSourceProvider::create_file_provider(".");
}
else
{
provider = _provider->clone();
}
sample_data = NULL;
}
CL_Sample::~CL_Sample()
{
delete[] sample_data;
delete provider;
}
void CL_Sample::load_data()
{
CL_InputSource *source = provider->open_source(sample_id.c_str());
cl_assert(source != NULL);
// Check to see if this is really a .wav-file
char temp[12];
source->read(temp, 4);
source->seek(4, CL_InputSource::seek_cur);
source->read(&temp[4], 8);
source->seek(4, CL_InputSource::seek_cur);
if (memcmp(temp, "RIFFWAVEfmt ", 12) != 0)
{
throw CL_Error("Invalid RIFF WAVE header!");
}
// cl_assert(!(memcmp(temp, "RIFFWAVEfmt ", 12)));
WAVE_FORMAT format;
format.formatTag = source->read_short16();
format.nChannels = source->read_ushort16();
format.nSamplesPerSec = source->read_uint32();
format.nAvgBytesPerSec = source->read_uint32();
format.nBlockAlign = source->read_ushort16();
// FIXME: find a better way to handle format struct padding
source->read(temp, 2);
// Another sanity check
source->read(temp, 4);
temp[4] = 0;
if (memcmp(temp, "data", 4) != 0)
{
throw CL_Error("Invalid RIFF data chunk!");
}
// cl_assert(!(memcmp(temp, "data", 4)));
sample_size = source->read_uint32();
sample_freq = format.nSamplesPerSec;
int bytes_per_sample = format.nAvgBytesPerSec / format.nSamplesPerSec;
if (format.nChannels == 2 && bytes_per_sample == 4) sample_format = sf_16bit_signed_stereo;
else if (format.nChannels == 2 && bytes_per_sample == 2) sample_format = sf_8bit_signed_stereo;
else if (format.nChannels == 1 && bytes_per_sample == 2) sample_format = sf_16bit_signed;
else if (format.nChannels == 1 && bytes_per_sample == 1) sample_format = sf_8bit_signed;
else
{
CL_Log::log("debug", "Invalid wave file format");
CL_Log::log("debug", "Sample size: %1", sample_size);
CL_Log::log("debug", "Sample frequency: %1", sample_freq);
CL_Log::log("debug", "Number of channels: %1", format.nChannels);
CL_Log::log("debug", "Number of bytes pr. sample: %1", bytes_per_sample);
throw CL_Error("Invalid wave file format");
}
sample_data = new signed char[sample_size];
if (sample_format == sf_8bit_signed || sample_format == sf_8bit_signed_stereo)
{
for (int i=0;i<sample_size;i++)
sample_data[i] = source->read_uchar8()-128;
}
else // 16 bit
{
for (int i=0;i<sample_size;i+=2)
*(short *)&sample_data[i] = source->read_short16();
}
delete source;
}
void CL_Sample::lock()
{
if (sample_data != NULL) return;
load_data();
}
void CL_Sample::unlock()
{
delete[] sample_data;
sample_data = NULL;
}
SoundFormat CL_Sample::get_format() const
{
return sample_format;
}
int CL_Sample::data_size() const
{
return sample_size;
}
void *CL_Sample::get_data() const
{
return sample_data;
}
int CL_Sample::get_frequency() const
{
return sample_freq;
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -