Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorJoerg Mueller <nexyon@gmail.com>2011-08-06 21:57:20 +0400
committerJoerg Mueller <nexyon@gmail.com>2011-08-06 21:57:20 +0400
commitc334bf69a7282254bb80bb2896bd8716930a4adf (patch)
tree08291f87da9ba64b80c881d704cf251b884ba7c2 /intern
parente73cf35f4ad470d553540d6adbe89af5cc0c1f4f (diff)
3D Audio GSoC:
Mixdown functionality. * Mixdown possible via libsndfile and ffmpeg! * Fixed some ffmpeg deprecation warnings * Mixdown UI only shows working Container, Codec and Format combinations! * Minor bugs and warnings fixed
Diffstat (limited to 'intern')
-rw-r--r--intern/audaspace/CMakeLists.txt7
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp31
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGReader.h4
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp303
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h114
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp21
-rw-r--r--intern/audaspace/intern/AUD_C-API.h4
-rw-r--r--intern/audaspace/intern/AUD_ConverterFunctions.cpp6
-rw-r--r--intern/audaspace/intern/AUD_FileWriter.cpp97
-rw-r--r--intern/audaspace/intern/AUD_FileWriter.h58
-rw-r--r--intern/audaspace/intern/AUD_IReader.h15
-rw-r--r--intern/audaspace/intern/AUD_IWriter.h69
-rw-r--r--intern/audaspace/intern/AUD_NULLDevice.cpp4
-rw-r--r--intern/audaspace/intern/AUD_NULLDevice.h2
-rw-r--r--intern/audaspace/intern/AUD_Space.h24
-rw-r--r--intern/audaspace/sndfile/AUD_SndFileWriter.cpp141
-rw-r--r--intern/audaspace/sndfile/AUD_SndFileWriter.h87
17 files changed, 952 insertions, 35 deletions
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt
index b08c5f62b29..8b7cb1d9e69 100644
--- a/intern/audaspace/CMakeLists.txt
+++ b/intern/audaspace/CMakeLists.txt
@@ -88,12 +88,15 @@ set(SRC
intern/AUD_ConverterReader.h
intern/AUD_FileFactory.cpp
intern/AUD_FileFactory.h
+ intern/AUD_FileWriter.cpp
+ intern/AUD_FileWriter.h
intern/AUD_I3DDevice.h
intern/AUD_I3DHandle.h
intern/AUD_IDevice.h
intern/AUD_IFactory.h
intern/AUD_IHandle.h
intern/AUD_IReader.h
+ intern/AUD_IWriter.h
intern/AUD_JOSResampleFactory.cpp
intern/AUD_JOSResampleFactory.h
intern/AUD_JOSResampleReader.cpp
@@ -184,9 +187,11 @@ if(WITH_CODEC_FFMPEG)
list(APPEND SRC
ffmpeg/AUD_FFMPEGFactory.cpp
ffmpeg/AUD_FFMPEGReader.cpp
+ ffmpeg/AUD_FFMPEGWriter.cpp
ffmpeg/AUD_FFMPEGFactory.h
ffmpeg/AUD_FFMPEGReader.h
+ ffmpeg/AUD_FFMPEGWriter.h
)
endif()
@@ -246,9 +251,11 @@ if(WITH_CODEC_SNDFILE)
list(APPEND SRC
sndfile/AUD_SndFileFactory.cpp
sndfile/AUD_SndFileReader.cpp
+ sndfile/AUD_SndFileWriter.cpp
sndfile/AUD_SndFileFactory.h
sndfile/AUD_SndFileReader.h
+ sndfile/AUD_SndFileWriter.h
)
endif()
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
index b7690d55383..a7534dbed32 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
@@ -176,11 +176,11 @@ static const char* fileopen_error = "AUD_FFMPEGReader: File couldn't be "
AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) :
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
- m_byteiocontext(NULL),
+ m_aviocontext(NULL),
m_membuf(NULL)
{
// open file
- if(av_open_input_file(&m_formatCtx, filename.c_str(), NULL, 0, NULL)!=0)
+ if(avformat_open_input(&m_formatCtx, filename.c_str(), NULL, NULL)!=0)
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
try
@@ -204,25 +204,20 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
{
m_membuf = reinterpret_cast<data_t*>(av_malloc(FF_MIN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE));
- m_byteiocontext = av_alloc_put_byte(m_membuf, FF_MIN_BUFFER_SIZE, 0, this,
- read_packet, NULL, seek_packet);
+ m_aviocontext = avio_alloc_context(m_membuf, FF_MIN_BUFFER_SIZE, 0, this,
+ read_packet, NULL, seek_packet);
- if(!m_byteiocontext)
+ if(!m_aviocontext)
{
- av_free(m_byteiocontext);
+ av_free(m_aviocontext);
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
}
- AVProbeData probe_data;
- probe_data.filename = "";
- probe_data.buf = reinterpret_cast<data_t*>(buffer.get()->getBuffer());
- probe_data.buf_size = buffer.get()->getSize();
- AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
-
- // open stream
- if(av_open_input_stream(&m_formatCtx, m_byteiocontext, "", fmt, NULL)!=0)
+ m_formatCtx = avformat_alloc_context();
+ m_formatCtx->pb = m_aviocontext;
+ if(avformat_open_input(&m_formatCtx, "", NULL, NULL)!=0)
{
- av_free(m_byteiocontext);
+ av_free(m_aviocontext);
AUD_THROW(AUD_ERROR_FILE, streamopen_error);
}
@@ -233,7 +228,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
catch(AUD_Exception&)
{
av_close_input_stream(m_formatCtx);
- av_free(m_byteiocontext);
+ av_free(m_aviocontext);
throw;
}
}
@@ -242,10 +237,10 @@ AUD_FFMPEGReader::~AUD_FFMPEGReader()
{
avcodec_close(m_codecCtx);
- if(m_byteiocontext)
+ if(m_aviocontext)
{
av_close_input_stream(m_formatCtx);
- av_free(m_byteiocontext);
+ av_free(m_aviocontext);
}
else
av_close_input_file(m_formatCtx);
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h
index 06d6fe1e5f6..222a3d8581a 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h
@@ -86,9 +86,9 @@ private:
AVCodecContext* m_codecCtx;
/**
- * The ByteIOContext to read the data from.
+ * The AVIOContext to read the data from.
*/
- ByteIOContext* m_byteiocontext;
+ AVIOContext* m_aviocontext;
/**
* The stream ID in the file.
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
new file mode 100644
index 00000000000..f2b7acc5ea2
--- /dev/null
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
@@ -0,0 +1,303 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
+ * \ingroup audffmpeg
+ */
+
+
+// needed for INT64_C
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#include "AUD_FFMPEGWriter.h"
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <libavformat/avio.h>
+}
+
+static const char* context_error = "AUD_FFMPEGWriter: Couldn't allocate context.";
+static const char* codec_error = "AUD_FFMPEGWriter: Invalid codec or codec not found.";
+static const char* stream_error = "AUD_FFMPEGWriter: Couldn't allocate stream.";
+static const char* format_error = "AUD_FFMPEGWriter: Unsupported sample format.";
+static const char* file_error = "AUD_FFMPEGWriter: File couldn't be written.";
+static const char* write_error = "AUD_FFMPEGWriter: Error writing packet.";
+
+AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) :
+ m_position(0),
+ m_specs(specs),
+ m_input_samples(0)
+{
+ static const char* formats[] = { NULL, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" };
+
+ if(avformat_alloc_output_context2(&m_formatCtx, NULL, formats[format], filename.c_str()))
+ AUD_THROW(AUD_ERROR_FFMPEG, context_error);
+
+ m_outputFmt = m_formatCtx->oformat;
+
+ switch(codec)
+ {
+ case AUD_CODEC_AAC:
+ m_outputFmt->audio_codec = CODEC_ID_AAC;
+ break;
+ case AUD_CODEC_AC3:
+ m_outputFmt->audio_codec = CODEC_ID_AC3;
+ break;
+ case AUD_CODEC_FLAC:
+ m_outputFmt->audio_codec = CODEC_ID_FLAC;
+ break;
+ case AUD_CODEC_MP2:
+ m_outputFmt->audio_codec = CODEC_ID_MP2;
+ break;
+ case AUD_CODEC_MP3:
+ m_outputFmt->audio_codec = CODEC_ID_MP3;
+ break;
+ case AUD_CODEC_PCM:
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_outputFmt->audio_codec = CODEC_ID_PCM_U8;
+ break;
+ case AUD_FORMAT_S16:
+ m_outputFmt->audio_codec = CODEC_ID_PCM_S16LE;
+ break;
+ case AUD_FORMAT_S24:
+ m_outputFmt->audio_codec = CODEC_ID_PCM_S24LE;
+ break;
+ case AUD_FORMAT_S32:
+ m_outputFmt->audio_codec = CODEC_ID_PCM_S32LE;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_outputFmt->audio_codec = CODEC_ID_PCM_F32LE;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_outputFmt->audio_codec = CODEC_ID_PCM_F64LE;
+ break;
+ default:
+ m_outputFmt->audio_codec = CODEC_ID_NONE;
+ break;
+ }
+ break;
+ case AUD_CODEC_VORBIS:
+ m_outputFmt->audio_codec = CODEC_ID_VORBIS;
+ break;
+ default:
+ m_outputFmt->audio_codec = CODEC_ID_NONE;
+ break;
+ }
+
+ try
+ {
+ if(m_outputFmt->audio_codec == CODEC_ID_NONE)
+ AUD_THROW(AUD_ERROR_SPECS, codec_error);
+
+ m_stream = av_new_stream(m_formatCtx, 0);
+ if(!m_stream)
+ AUD_THROW(AUD_ERROR_FFMPEG, stream_error);
+
+ m_codecCtx = m_stream->codec;
+ m_codecCtx->codec_id = m_outputFmt->audio_codec;
+ m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
+ m_codecCtx->bit_rate = bitrate;
+ m_codecCtx->sample_rate = int(m_specs.rate);
+ m_codecCtx->channels = m_specs.channels;
+ m_codecCtx->time_base = (AVRational){1, m_codecCtx->sample_rate};
+
+ switch(m_specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_float_u8;
+ m_codecCtx->sample_fmt = SAMPLE_FMT_U8;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_float_s16;
+ m_codecCtx->sample_fmt = SAMPLE_FMT_S16;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_float_s32;
+ m_codecCtx->sample_fmt = SAMPLE_FMT_S32;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_copy<float>;
+ m_codecCtx->sample_fmt = SAMPLE_FMT_FLT;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_float_double;
+ m_codecCtx->sample_fmt = SAMPLE_FMT_DBL;
+ break;
+ default:
+ AUD_THROW(AUD_ERROR_FFMPEG, format_error);
+ }
+
+ try
+ {
+ if(m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
+ m_codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+
+ AVCodec* codec = avcodec_find_encoder(m_codecCtx->codec_id);
+ if(!codec)
+ AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
+
+ if(avcodec_open(m_codecCtx, codec))
+ AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
+
+ m_output_buffer.resize(FF_MIN_BUFFER_SIZE);
+ int samplesize = AUD_MAX(AUD_SAMPLE_SIZE(m_specs), AUD_DEVICE_SAMPLE_SIZE(m_specs));
+
+ if(m_codecCtx->frame_size <= 1)
+ m_input_size = 0;
+ else
+ {
+ m_input_buffer.resize(m_codecCtx->frame_size * samplesize);
+ m_input_size = m_codecCtx->frame_size;
+ }
+
+ try
+ {
+ if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_WRONLY))
+ AUD_THROW(AUD_ERROR_FILE, file_error);
+
+ avformat_write_header(m_formatCtx, NULL);
+ }
+ catch(AUD_Exception&)
+ {
+ avcodec_close(m_codecCtx);
+ av_freep(&m_formatCtx->streams[0]->codec);
+ throw;
+ }
+ }
+ catch(AUD_Exception&)
+ {
+ av_freep(&m_formatCtx->streams[0]);
+ throw;
+ }
+ }
+ catch(AUD_Exception&)
+ {
+ av_free(m_formatCtx);
+ throw;
+ }
+}
+
+AUD_FFMPEGWriter::~AUD_FFMPEGWriter()
+{
+ // writte missing data
+ if(m_input_samples)
+ {
+ sample_t* buf = m_input_buffer.getBuffer();
+ memset(buf + m_specs.channels * m_input_samples, 0,
+ (m_input_size - m_input_samples) * AUD_DEVICE_SAMPLE_SIZE(m_specs));
+
+ encode(buf);
+ }
+
+ av_write_trailer(m_formatCtx);
+
+ avcodec_close(m_codecCtx);
+
+ av_freep(&m_formatCtx->streams[0]->codec);
+ av_freep(&m_formatCtx->streams[0]);
+
+ avio_close(m_formatCtx->pb);
+ av_free(m_formatCtx);
+}
+
+int AUD_FFMPEGWriter::getPosition() const
+{
+ return m_position;
+}
+
+AUD_DeviceSpecs AUD_FFMPEGWriter::getSpecs() const
+{
+ return m_specs;
+}
+
+void AUD_FFMPEGWriter::encode(sample_t* data)
+{
+ sample_t* outbuf = m_output_buffer.getBuffer();
+
+ // convert first
+ if(m_input_size)
+ m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_size * m_specs.channels);
+
+ AVPacket packet;
+ av_init_packet(&packet);
+ packet.size = avcodec_encode_audio(m_codecCtx, reinterpret_cast<uint8_t*>(outbuf), m_output_buffer.getSize(), reinterpret_cast<short*>(data));
+ if(m_codecCtx->coded_frame && m_codecCtx->coded_frame->pts != AV_NOPTS_VALUE)
+ packet.pts = av_rescale_q(m_codecCtx->coded_frame->pts, m_codecCtx->time_base, m_stream->time_base);
+ packet.flags |= AV_PKT_FLAG_KEY;
+ packet.stream_index = m_stream->index;
+ packet.data = reinterpret_cast<uint8_t*>(outbuf);
+
+ if(av_interleaved_write_frame(m_formatCtx, &packet))
+ AUD_THROW(AUD_ERROR_FFMPEG, write_error);
+}
+
+void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer)
+{
+ unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
+
+ if(m_input_size)
+ {
+ sample_t* inbuf = m_input_buffer.getBuffer();
+
+ while(length)
+ {
+ unsigned int len = AUD_MIN(m_input_size - m_input_samples, length);
+
+ memcpy(inbuf + m_input_samples * m_specs.channels, buffer, len * samplesize);
+
+ buffer += len * m_specs.channels;
+ m_input_samples += len;
+ m_position += len;
+ length -= len;
+
+ if(m_input_samples == m_input_size)
+ {
+ encode(inbuf);
+
+ m_input_samples = 0;
+ }
+ }
+ }
+ else // PCM data, can write directly!
+ {
+ int samplesize = AUD_SAMPLE_SIZE(m_specs);
+ if(m_output_buffer.getSize() != length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8)
+ m_output_buffer.resize(length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8);
+ m_input_buffer.assureSize(length * AUD_MAX(AUD_DEVICE_SAMPLE_SIZE(m_specs), samplesize));
+
+ sample_t* buf = m_input_buffer.getBuffer();
+ m_convert(reinterpret_cast<data_t*>(buf), reinterpret_cast<data_t*>(buffer), length * m_specs.channels);
+
+ encode(buf);
+
+ m_position += length;
+ }
+}
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h
new file mode 100644
index 00000000000..618ec9402ce
--- /dev/null
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h
@@ -0,0 +1,114 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/ffmpeg/AUD_FFMPEGWriter.h
+ * \ingroup audffmpeg
+ */
+
+
+#ifndef AUD_FFMPEGWRITER
+#define AUD_FFMPEGWRITER
+
+#include "AUD_ConverterFunctions.h"
+#include "AUD_Buffer.h"
+#include "AUD_IWriter.h"
+
+#include <string>
+
+struct AVCodecContext;
+extern "C" {
+#include <libavformat/avformat.h>
+}
+
+/**
+ * This class writes a sound file via ffmpeg.
+ */
+class AUD_FFMPEGWriter : public AUD_IWriter
+{
+private:
+ /**
+ * The current position in samples.
+ */
+ int m_position;
+
+ /**
+ * The specification of the audio data.
+ */
+ AUD_DeviceSpecs m_specs;
+
+ /**
+ * The AVFormatContext structure for using ffmpeg.
+ */
+ AVFormatContext* m_formatCtx;
+
+ /**
+ * The AVCodecContext structure for using ffmpeg.
+ */
+ AVCodecContext* m_codecCtx;
+
+ AVOutputFormat* m_outputFmt;
+
+ AVStream* m_stream;
+
+ AUD_Buffer m_input_buffer;
+
+ AUD_Buffer m_output_buffer;
+
+ unsigned int m_input_samples;
+
+ unsigned int m_input_size;
+
+ /**
+ * Converter function.
+ */
+ AUD_convert_f m_convert;
+
+ // hide copy constructor and operator=
+ AUD_FFMPEGWriter(const AUD_FFMPEGWriter&);
+ AUD_FFMPEGWriter& operator=(const AUD_FFMPEGWriter&);
+
+ void encode(sample_t* data);
+
+public:
+ /**
+ * Creates a new writer.
+ * \param filename The path to the file to be read.
+ * \exception AUD_Exception Thrown if the file specified does not exist or
+ * cannot be read with ffmpeg.
+ */
+ AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
+
+ /**
+ * Destroys the writer and closes the file.
+ */
+ virtual ~AUD_FFMPEGWriter();
+
+ virtual int getPosition() const;
+ virtual AUD_DeviceSpecs getSpecs() const;
+ virtual void write(unsigned int length, sample_t* buffer);
+};
+
+#endif //AUD_FFMPEGWRITER
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index 23245b56b20..467ee736b7f 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -48,6 +48,7 @@
#include "AUD_I3DDevice.h"
#include "AUD_I3DHandle.h"
#include "AUD_FileFactory.h"
+#include "AUD_FileWriter.h"
#include "AUD_StreamBufferFactory.h"
#include "AUD_DelayFactory.h"
#include "AUD_LimiterFactory.h"
@@ -1153,3 +1154,23 @@ void* AUD_getSet(void* set)
return NULL;
}
+
+const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate)
+{
+ try
+ {
+ AUD_SequencerFactory* f = dynamic_cast<AUD_SequencerFactory*>(sound->get());
+
+ f->setSpecs(specs.specs);
+ AUD_Reference<AUD_IReader> reader = f->createReader();
+ reader->seek(start);
+ AUD_Reference<AUD_IWriter> writer = AUD_FileWriter::createWriter(filename, specs, format, codec, bitrate);
+ AUD_FileWriter::writeReader(reader, writer, length, buffersize);
+
+ return NULL;
+ }
+ catch(AUD_Exception& e)
+ {
+ return e.str;
+ }
+}
diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h
index a6ef34280c2..abcbd215074 100644
--- a/intern/audaspace/intern/AUD_C-API.h
+++ b/intern/audaspace/intern/AUD_C-API.h
@@ -508,7 +508,7 @@ extern AUD_Sound* AUD_copy(AUD_Sound* sound);
extern void AUD_freeHandle(AUD_Handle* channel);
-extern void* AUD_createSet();
+extern void* AUD_createSet(void);
extern void AUD_destroySet(void* set);
@@ -518,6 +518,8 @@ extern void AUD_addSet(void* set, void* entry);
extern void* AUD_getSet(void* set);
+extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
+
#ifdef WITH_PYTHON
extern PyObject* AUD_getPythonFactory(AUD_Sound* sound);
diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.cpp b/intern/audaspace/intern/AUD_ConverterFunctions.cpp
index c45fde72b1b..f7be2ca805f 100644
--- a/intern/audaspace/intern/AUD_ConverterFunctions.cpp
+++ b/intern/audaspace/intern/AUD_ConverterFunctions.cpp
@@ -35,10 +35,10 @@
#define AUD_U8_0 0x80
#define AUD_S16_MAX 0x7FFF
#define AUD_S16_MIN 0x8000
-#define AUD_S16_FLT 32768.0f
+#define AUD_S16_FLT 32767.0f
#define AUD_S32_MAX 0x7FFFFFFF
#define AUD_S32_MIN 0x80000000
-#define AUD_S32_FLT 2147483648.0f
+#define AUD_S32_FLT 2147483647.0f
#define AUD_FLT_MAX 1.0f
#define AUD_FLT_MIN -1.0f
@@ -379,7 +379,7 @@ void AUD_convert_float_double(data_t* target, data_t* source, int length)
{
float* s = (float*) source;
double* t = (double*) target;
- for(int i = length - 1; i >= 0; i++)
+ for(int i = length - 1; i >= 0; i--)
t[i] = s[i];
}
diff --git a/intern/audaspace/intern/AUD_FileWriter.cpp b/intern/audaspace/intern/AUD_FileWriter.cpp
new file mode 100644
index 00000000000..a5ef592ea17
--- /dev/null
+++ b/intern/audaspace/intern/AUD_FileWriter.cpp
@@ -0,0 +1,97 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_FileWriter.cpp
+ * \ingroup audaspaceintern
+ */
+
+#ifdef WITH_FFMPEG
+// needed for INT64_C
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+#include "AUD_FFMPEGWriter.h"
+#endif
+
+#ifdef WITH_SNDFILE
+#include "AUD_SndFileWriter.h"
+#endif
+
+#include "AUD_FileWriter.h"
+#include "AUD_Buffer.h"
+
+static const char* write_error = "AUD_FileWriter: File couldn't be written.";
+
+AUD_Reference<AUD_IWriter> AUD_FileWriter::createWriter(std::string filename,AUD_DeviceSpecs specs,
+ AUD_Container format, AUD_Codec codec, unsigned int bitrate)
+{
+#ifdef WITH_SNDFILE
+ try
+ {
+ return new AUD_SndFileWriter(filename, specs, format, codec, bitrate);
+ }
+ catch(AUD_Exception&) {}
+#endif
+
+#ifdef WITH_FFMPEG
+ try
+ {
+ return new AUD_FFMPEGWriter(filename, specs, format, codec, bitrate);
+ }
+ catch(AUD_Exception&) {}
+#endif
+
+ AUD_THROW(AUD_ERROR_SPECS, write_error);
+}
+
+void AUD_FileWriter::writeReader(AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_IWriter> writer, unsigned int length, unsigned int buffersize)
+{
+ AUD_Buffer buffer(buffersize * AUD_SAMPLE_SIZE(writer->getSpecs()));
+ sample_t* buf = buffer.getBuffer();
+
+ int len;
+ bool eos = false;
+ int channels = writer->getSpecs().channels;
+
+ for(unsigned int pos = 0; ((pos < length) || (length <= 0)) && !eos; pos += len)
+ {
+ len = buffersize;
+ if((len > length - pos) && (length > 0))
+ len = length - pos;
+ reader->read(len, eos, buf);
+
+ for(int i = 0; i < len * channels; i++)
+ {
+ // clamping!
+ if(buf[i] > 1)
+ buf[i] = 1;
+ else if(buf[i] < -1)
+ buf[i] = -1;
+ }
+
+ writer->write(len, buf);
+ }
+}
diff --git a/intern/audaspace/intern/AUD_FileWriter.h b/intern/audaspace/intern/AUD_FileWriter.h
new file mode 100644
index 00000000000..60aec1b5927
--- /dev/null
+++ b/intern/audaspace/intern/AUD_FileWriter.h
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_FileWriter.h
+ * \ingroup audaspaceintern
+ */
+
+
+#ifndef AUD_FILEWRITER
+#define AUD_FILEWRITER
+
+#include <string>
+
+#include "AUD_Reference.h"
+
+#include "AUD_IWriter.h"
+#include "AUD_IReader.h"
+
+/**
+ * This factory tries to read a sound file via all available file readers.
+ */
+class AUD_FileWriter
+{
+private:
+ // hide default constructor, copy constructor and operator=
+ AUD_FileWriter();
+ AUD_FileWriter(const AUD_FileWriter&);
+ AUD_FileWriter& operator=(const AUD_FileWriter&);
+
+public:
+ static AUD_Reference<AUD_IWriter> createWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
+ static void writeReader(AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_IWriter> writer, unsigned int length, unsigned int buffersize);
+};
+
+#endif //AUD_FILEWRITER
diff --git a/intern/audaspace/intern/AUD_IReader.h b/intern/audaspace/intern/AUD_IReader.h
index b1a282c9d49..5fc2cd62fb2 100644
--- a/intern/audaspace/intern/AUD_IReader.h
+++ b/intern/audaspace/intern/AUD_IReader.h
@@ -49,27 +49,22 @@ public:
/**
* Tells whether the source provides seeking functionality or not.
* \warning This doesn't mean that the seeking always has to succeed.
- * \return Always returns true for readers of the buffer type.
- * \see getType
+ * \return Always returns true for readers of buffering types.
*/
virtual bool isSeekable() const=0;
/**
* Seeks to a specific position in the source.
- * This function must work for buffer type readers.
* \param position The position to seek for measured in samples. To get
* from a given time to the samples you simply have to multiply the
* time value in seconds with the sample rate of the reader.
* \warning This may work or not, depending on the actual reader.
- * \see getType
*/
virtual void seek(int position)=0;
/**
* Returns an approximated length of the source in samples.
- * For readers of the type buffer this has to return a correct value!
* \return The length as sample count. May be negative if unknown.
- * \see getType
*/
virtual int getLength() const=0;
@@ -77,10 +72,8 @@ public:
* Returns the position of the source as a sample count value.
* \return The current position in the source. A negative value indicates
* that the position is unknown.
- * \warning The value returned doesn't always have to be correct for readers
- * of the stream type, especially after seeking, it must though for
- * the buffer ones.
- * \see getType
+ * \warning The value returned doesn't always have to be correct for readers,
+ * especially after seeking.
*/
virtual int getPosition() const=0;
@@ -98,7 +91,7 @@ public:
* there were only fewer samples available.
* A smaller value also indicates the end of the reader.
* \param[out] eos End of stream, whether the end is reached or not.
- * \param[int] buffer The pointer to the buffer to read into.
+ * \param[in] buffer The pointer to the buffer to read into.
*/
virtual void read(int& length, bool& eos, sample_t* buffer)=0;
};
diff --git a/intern/audaspace/intern/AUD_IWriter.h b/intern/audaspace/intern/AUD_IWriter.h
new file mode 100644
index 00000000000..944bce961c3
--- /dev/null
+++ b/intern/audaspace/intern/AUD_IWriter.h
@@ -0,0 +1,69 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/intern/AUD_IWriter.h
+ * \ingroup audaspaceintern
+ */
+
+
+#ifndef AUD_IWRITER
+#define AUD_IWRITER
+
+#include "AUD_Space.h"
+
+/**
+ * This class represents a sound sink where audio data can be written to.
+ */
+class AUD_IWriter
+{
+public:
+ /**
+ * Destroys the writer.
+ */
+ virtual ~AUD_IWriter(){}
+
+ /**
+ * Returns how many samples have been written so far.
+ * \return The writing position as sample count. May be negative if unknown.
+ */
+ virtual int getPosition() const=0;
+
+ /**
+ * Returns the specification of the audio data being written into the sink.
+ * \return The AUD_DeviceSpecs structure.
+ * \note Regardless of the format the input still has to be float!
+ */
+ virtual AUD_DeviceSpecs getSpecs() const=0;
+
+ /**
+ * Request to write the next length samples out into the sink.
+ * \param length The count of samples to write.
+ * \param buffer The pointer to the buffer containing the data.
+ */
+ virtual void write(unsigned int length, sample_t* buffer)=0;
+};
+
+#endif //AUD_IWRITER
diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp
index c3a8c754cb2..78a02d32cdd 100644
--- a/intern/audaspace/intern/AUD_NULLDevice.cpp
+++ b/intern/audaspace/intern/AUD_NULLDevice.cpp
@@ -40,6 +40,10 @@ AUD_NULLDevice::AUD_NULLDevice()
{
}
+AUD_NULLDevice::~AUD_NULLDevice()
+{
+}
+
AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const
{
AUD_DeviceSpecs specs;
diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h
index 69ca5b74f3b..04458575f1c 100644
--- a/intern/audaspace/intern/AUD_NULLDevice.h
+++ b/intern/audaspace/intern/AUD_NULLDevice.h
@@ -46,6 +46,8 @@ public:
*/
AUD_NULLDevice();
+ virtual ~AUD_NULLDevice();
+
virtual AUD_DeviceSpecs getSpecs() const;
virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);
virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h
index 117c37b56ba..4d0a06e37b2 100644
--- a/intern/audaspace/intern/AUD_Space.h
+++ b/intern/audaspace/intern/AUD_Space.h
@@ -169,6 +169,30 @@ typedef enum
AUD_AP_ORIENTATION
} AUD_AnimateablePropertyType;
+typedef enum
+{
+ AUD_CONTAINER_INVALID = 0,
+ AUD_CONTAINER_AC3,
+ AUD_CONTAINER_FLAC,
+ AUD_CONTAINER_MATROSKA,
+ AUD_CONTAINER_MP2,
+ AUD_CONTAINER_MP3,
+ AUD_CONTAINER_OGG,
+ AUD_CONTAINER_WAV
+} AUD_Container;
+
+typedef enum
+{
+ AUD_CODEC_INVALID = 0,
+ AUD_CODEC_AAC,
+ AUD_CODEC_AC3,
+ AUD_CODEC_FLAC,
+ AUD_CODEC_MP2,
+ AUD_CODEC_MP3,
+ AUD_CODEC_PCM,
+ AUD_CODEC_VORBIS
+} AUD_Codec;
+
/// Sample type.(float samples)
typedef float sample_t;
diff --git a/intern/audaspace/sndfile/AUD_SndFileWriter.cpp b/intern/audaspace/sndfile/AUD_SndFileWriter.cpp
new file mode 100644
index 00000000000..ba59cd3d9d7
--- /dev/null
+++ b/intern/audaspace/sndfile/AUD_SndFileWriter.cpp
@@ -0,0 +1,141 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/sndfile/AUD_SndFileWriter.cpp
+ * \ingroup audsndfile
+ */
+
+
+#include "AUD_SndFileWriter.h"
+
+#include <cstring>
+
+static const char* fileopen_error = "AUD_SndFileWriter: File couldn't be written.";
+static const char* format_error = "AUD_SndFileWriter: Unsupported format.";
+
+AUD_SndFileWriter::AUD_SndFileWriter(std::string filename, AUD_DeviceSpecs specs,
+ AUD_Container format, AUD_Codec codec, unsigned int bitrate) :
+ m_specs(specs)
+{
+ SF_INFO sfinfo;
+
+ sfinfo.channels = specs.channels;
+ sfinfo.samplerate = int(specs.rate);
+
+ switch(format)
+ {
+ case AUD_CONTAINER_FLAC:
+ sfinfo.format = SF_FORMAT_FLAC;
+ switch(specs.format)
+ {
+ case AUD_FORMAT_S16:
+ sfinfo.format |= SF_FORMAT_PCM_16;
+ break;
+ case AUD_FORMAT_S24:
+ sfinfo.format |= SF_FORMAT_PCM_24;
+ break;
+ case AUD_FORMAT_S32:
+ sfinfo.format |= SF_FORMAT_PCM_32;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ sfinfo.format |= SF_FORMAT_FLOAT;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ sfinfo.format |= SF_FORMAT_DOUBLE;
+ break;
+ default:
+ sfinfo.format = 0;
+ break;
+ }
+ break;
+ case AUD_CONTAINER_OGG:
+ if(codec == AUD_CODEC_VORBIS)
+ sfinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS;
+ else
+ sfinfo.format = 0;
+ break;
+ case AUD_CONTAINER_WAV:
+ sfinfo.format = SF_FORMAT_WAV;
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ sfinfo.format |= SF_FORMAT_PCM_U8;
+ break;
+ case AUD_FORMAT_S16:
+ sfinfo.format |= SF_FORMAT_PCM_16;
+ break;
+ case AUD_FORMAT_S24:
+ sfinfo.format |= SF_FORMAT_PCM_24;
+ break;
+ case AUD_FORMAT_S32:
+ sfinfo.format |= SF_FORMAT_PCM_32;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ sfinfo.format |= SF_FORMAT_FLOAT;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ sfinfo.format |= SF_FORMAT_DOUBLE;
+ break;
+ default:
+ sfinfo.format = 0;
+ break;
+ }
+ break;
+ default:
+ sfinfo.format = 0;
+ break;
+ }
+
+ if(sfinfo.format == 0)
+ AUD_THROW(AUD_ERROR_SPECS, format_error);
+
+ m_sndfile = sf_open(filename.c_str(), SFM_WRITE, &sfinfo);
+
+ if(!m_sndfile)
+ AUD_THROW(AUD_ERROR_FILE, fileopen_error);
+}
+
+AUD_SndFileWriter::~AUD_SndFileWriter()
+{
+ sf_close(m_sndfile);
+}
+
+int AUD_SndFileWriter::getPosition() const
+{
+ return m_position;
+}
+
+AUD_DeviceSpecs AUD_SndFileWriter::getSpecs() const
+{
+ return m_specs;
+}
+
+void AUD_SndFileWriter::write(unsigned int length, sample_t* buffer)
+{
+ length = sf_writef_float(m_sndfile, buffer, length);
+
+ m_position += length;
+}
diff --git a/intern/audaspace/sndfile/AUD_SndFileWriter.h b/intern/audaspace/sndfile/AUD_SndFileWriter.h
new file mode 100644
index 00000000000..63f9e9e1371
--- /dev/null
+++ b/intern/audaspace/sndfile/AUD_SndFileWriter.h
@@ -0,0 +1,87 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/sndfile/AUD_SndFileWriter.h
+ * \ingroup audsndfile
+ */
+
+
+#ifndef AUD_SNDFILEWRITER
+#define AUD_SNDFILEWRITER
+
+#include "AUD_IWriter.h"
+//#include "AUD_Buffer.h"
+
+#include <string>
+#include <sndfile.h>
+
+typedef sf_count_t (*sf_read_f)(SNDFILE *sndfile, void *ptr, sf_count_t frames);
+
+/**
+ * This class writes a sound file via libsndfile.
+ */
+class AUD_SndFileWriter : public AUD_IWriter
+{
+private:
+ /**
+ * The current position in samples.
+ */
+ int m_position;
+
+ /**
+ * The specification of the audio data.
+ */
+ AUD_DeviceSpecs m_specs;
+
+ /**
+ * The sndfile.
+ */
+ SNDFILE* m_sndfile;
+
+ // hide copy constructor and operator=
+ AUD_SndFileWriter(const AUD_SndFileWriter&);
+ AUD_SndFileWriter& operator=(const AUD_SndFileWriter&);
+
+public:
+ /**
+ * Creates a new writer.
+ * \param filename The path to the file to be read.
+ * \exception AUD_Exception Thrown if the file specified cannot be written
+ * with libsndfile.
+ */
+ AUD_SndFileWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
+
+ /**
+ * Destroys the writer and closes the file.
+ */
+ virtual ~AUD_SndFileWriter();
+
+ virtual int getPosition() const;
+ virtual AUD_DeviceSpecs getSpecs() const;
+ virtual void write(unsigned int length, sample_t* buffer);
+};
+
+#endif //AUD_SNDFILEWRITER