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
diff options
context:
space:
mode:
Diffstat (limited to 'intern/audaspace/SDL/AUD_SDLMixerReader.cpp')
-rw-r--r--intern/audaspace/SDL/AUD_SDLMixerReader.cpp214
1 files changed, 214 insertions, 0 deletions
diff --git a/intern/audaspace/SDL/AUD_SDLMixerReader.cpp b/intern/audaspace/SDL/AUD_SDLMixerReader.cpp
new file mode 100644
index 00000000000..1a0d990eaf2
--- /dev/null
+++ b/intern/audaspace/SDL/AUD_SDLMixerReader.cpp
@@ -0,0 +1,214 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 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 Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_SDLMixerReader.h"
+#include "AUD_Buffer.h"
+
+inline Uint16 AUD_TO_SDL(AUD_SampleFormat format)
+{
+ // SDL only supports 8 and 16 bit audio
+ switch(format)
+ {
+ case AUD_FORMAT_U8:
+ return AUDIO_U8;
+ case AUD_FORMAT_S16:
+ return AUDIO_S16SYS;
+ default:
+ AUD_THROW(AUD_ERROR_SDL);
+ }
+}
+
+// greatest common divisor
+inline int gcd(int a, int b)
+{
+ int c;
+
+ // make sure a is the bigger
+ if(b > a)
+ {
+ c = b;
+ b = a;
+ a = c;
+ }
+
+ // greetings from Euclides
+ while(b != 0)
+ {
+ c = a % b;
+ a = b;
+ b = c;
+ }
+ return a;
+}
+
+AUD_SDLMixerReader::AUD_SDLMixerReader(AUD_IReader* reader,
+ AUD_Specs specs)
+{
+ if(reader == NULL)
+ AUD_THROW(AUD_ERROR_READER);
+
+ m_reader = reader;
+ m_tspecs = specs;
+ m_sspecs = reader->getSpecs();
+
+ try
+ {
+ // SDL only supports 8 and 16 bit sample formats
+ if(SDL_BuildAudioCVT(&m_cvt,
+ AUD_TO_SDL(m_sspecs.format),
+ m_sspecs.channels,
+ m_sspecs.rate,
+ AUD_TO_SDL(specs.format),
+ specs.channels,
+ specs.rate) == -1)
+ AUD_THROW(AUD_ERROR_SDL);
+ }
+ catch(AUD_Exception e)
+ {
+ delete m_reader; AUD_DELETE("reader")
+ throw;
+ }
+
+ m_eor = false;
+ m_rsposition = 0;
+ m_rssize = 0;
+ m_ssize = m_sspecs.rate / gcd(specs.rate, m_sspecs.rate);
+ m_tsize = m_tspecs.rate * m_ssize / m_sspecs.rate;
+
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+ m_rsbuffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_SDLMixerReader::~AUD_SDLMixerReader()
+{
+ delete m_reader; AUD_DELETE("reader")
+ delete m_buffer; AUD_DELETE("buffer")
+ delete m_rsbuffer; AUD_DELETE("buffer")
+}
+
+bool AUD_SDLMixerReader::isSeekable()
+{
+ return m_reader->isSeekable();
+}
+
+void AUD_SDLMixerReader::seek(int position)
+{
+ m_reader->seek(position * m_ssize / m_tsize);
+ m_eor = false;
+}
+
+int AUD_SDLMixerReader::getLength()
+{
+ return m_reader->getLength() * m_tsize / m_ssize;
+}
+
+int AUD_SDLMixerReader::getPosition()
+{
+ return m_reader->getPosition() * m_tsize / m_ssize;
+}
+
+AUD_Specs AUD_SDLMixerReader::getSpecs()
+{
+ return m_tspecs;
+}
+
+AUD_ReaderType AUD_SDLMixerReader::getType()
+{
+ return m_reader->getType();
+}
+
+bool AUD_SDLMixerReader::notify(AUD_Message &message)
+{
+ return m_reader->notify(message);
+}
+
+void AUD_SDLMixerReader::read(int & length, sample_t* & buffer)
+{
+ // sample count for the target buffer without getting a shift
+ int tns = length + m_tsize - length % m_tsize;
+ // sample count for the source buffer without getting a shift
+ int sns = tns * m_ssize / m_tsize;
+ // target sample size
+ int tss = AUD_SAMPLE_SIZE(m_tspecs);
+ // source sample size
+ int sss = AUD_SAMPLE_SIZE(m_sspecs);
+
+ // input is output buffer
+ int buf_size = AUD_MAX(tns*tss, sns*sss);
+
+ // resize if necessary
+ if(m_rsbuffer->getSize() < buf_size)
+ m_rsbuffer->resize(buf_size, true);
+
+ if(m_buffer->getSize() < length*tss)
+ m_buffer->resize(length*tss);
+
+ buffer = m_buffer->getBuffer();
+ int size;
+ int index = 0;
+ sample_t* buf;
+
+ while(index < length)
+ {
+ if(m_rsposition == m_rssize)
+ {
+ // no more data
+ if(m_eor)
+ length = index;
+ // mix
+ else
+ {
+ // read from source
+ size = sns;
+ m_reader->read(size, buf);
+
+ // prepare
+ m_cvt.buf = m_rsbuffer->getBuffer();
+ m_cvt.len = size*sss;
+ memcpy(m_cvt.buf, buf, size*sss);
+
+ // convert
+ SDL_ConvertAudio(&m_cvt);
+
+ // end of reader
+ if(size < sns)
+ m_eor = true;
+
+ m_rsposition = 0;
+ m_rssize = size * m_tsize / m_ssize;
+ }
+ }
+
+ // size to copy
+ size = AUD_MIN(m_rssize-m_rsposition, length-index);
+
+ // copy
+ memcpy(m_buffer->getBuffer() + index * tss,
+ m_rsbuffer->getBuffer() + m_rsposition * tss,
+ size*tss);
+ m_rsposition += size;
+ index += size;
+ }
+}