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:
authorJoerg Mueller <nexyon@gmail.com>2011-06-22 00:25:48 +0400
committerJoerg Mueller <nexyon@gmail.com>2011-06-22 00:25:48 +0400
commitd5eaffda23274271e28bf499bd8d4555b0077079 (patch)
treeaeea31ffdddc329474cc62a6c5bd1371daf12f9a /intern/audaspace
parentc89b4e4b665757e0a164e98985d2f5d1c6843fa0 (diff)
3D Audio GSoC:
Dynamic resampling for libsamplerate and linear resampling.
Diffstat (limited to 'intern/audaspace')
-rw-r--r--intern/audaspace/FX/AUD_ReverseReader.cpp2
-rw-r--r--intern/audaspace/SRC/AUD_SRCResampleFactory.cpp7
-rw-r--r--intern/audaspace/SRC/AUD_SRCResampleReader.cpp57
-rw-r--r--intern/audaspace/SRC/AUD_SRCResampleReader.h17
-rw-r--r--intern/audaspace/intern/AUD_LinearResampleFactory.cpp7
-rw-r--r--intern/audaspace/intern/AUD_LinearResampleReader.cpp138
-rw-r--r--intern/audaspace/intern/AUD_LinearResampleReader.h22
7 files changed, 157 insertions, 93 deletions
diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp
index 1a5083d3eb4..73f6830f3fa 100644
--- a/intern/audaspace/FX/AUD_ReverseReader.cpp
+++ b/intern/audaspace/FX/AUD_ReverseReader.cpp
@@ -76,7 +76,7 @@ void AUD_ReverseReader::read(int& length, bool& eos, sample_t* buffer)
const AUD_Specs specs = getSpecs();
const int samplesize = AUD_SAMPLE_SIZE(specs);
- sample_t temp[10];
+ sample_t temp[AUD_CHANNEL_MAX];
int len = length;
diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp
index 15e96f6ff1d..3ae2c4fbd06 100644
--- a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp
+++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp
@@ -40,10 +40,5 @@ AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Reference<AUD_IFactory> facto
AUD_Reference<AUD_IReader> AUD_SRCResampleFactory::createReader()
{
- AUD_Reference<AUD_IReader> reader = getReader();
-
- if(reader->getSpecs().rate != m_specs.rate)
- reader = new AUD_SRCResampleReader(reader, m_specs.specs);
-
- return reader;
+ return new AUD_SRCResampleReader(getReader(), m_specs.specs);
}
diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp
index 59854a7a2c4..cd6b0ef8c50 100644
--- a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp
+++ b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp
@@ -46,17 +46,14 @@ static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be "
AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader,
AUD_Specs specs) :
AUD_EffectReader(reader),
- m_sspecs(reader->getSpecs()),
- m_factor(double(specs.rate) / double(m_sspecs.rate)),
- m_tspecs(specs),
+ m_rate(specs.rate),
+ m_channels(reader->getSpecs().channels),
m_position(0)
{
- m_tspecs.channels = m_sspecs.channels;
-
int error;
m_src = src_callback_new(src_callback,
SRC_SINC_MEDIUM_QUALITY,
- m_sspecs.channels,
+ m_channels,
&error,
this);
@@ -74,7 +71,11 @@ AUD_SRCResampleReader::~AUD_SRCResampleReader()
long AUD_SRCResampleReader::doCallback(float** data)
{
- int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(m_tspecs);
+ AUD_Specs specs;
+ specs.channels = m_channels;
+ specs.rate = m_rate;
+
+ int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(specs);
*data = m_buffer.getBuffer();
m_reader->read(length, m_eos, *data);
@@ -84,14 +85,18 @@ long AUD_SRCResampleReader::doCallback(float** data)
void AUD_SRCResampleReader::seek(int position)
{
- m_reader->seek(position / m_factor);
+ AUD_Specs specs = m_reader->getSpecs();
+ double factor = double(m_rate) / double(specs.rate);
+ m_reader->seek(position / factor);
src_reset(m_src);
m_position = position;
}
int AUD_SRCResampleReader::getLength() const
{
- return m_reader->getLength() * m_factor;
+ AUD_Specs specs = m_reader->getSpecs();
+ double factor = double(m_rate) / double(specs.rate);
+ return m_reader->getLength() * factor;
}
int AUD_SRCResampleReader::getPosition() const
@@ -101,18 +106,46 @@ int AUD_SRCResampleReader::getPosition() const
AUD_Specs AUD_SRCResampleReader::getSpecs() const
{
- return m_tspecs;
+ AUD_Specs specs = m_reader->getSpecs();
+ specs.rate = m_rate;
+ return specs;
}
void AUD_SRCResampleReader::read(int& length, bool& eos, sample_t* buffer)
{
+ AUD_Specs specs = m_reader->getSpecs();
+
+ double factor = double(m_rate) / double(specs.rate);
+
+ specs.rate = m_rate;
+
int size = length;
- m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_tspecs));
+ m_buffer.assureSize(length * AUD_SAMPLE_SIZE(specs));
+
+ if(specs.channels != m_channels)
+ {
+ src_delete(m_src);
+
+ m_channels = specs.channels;
+
+ int error;
+ m_src = src_callback_new(src_callback,
+ SRC_SINC_MEDIUM_QUALITY,
+ m_channels,
+ &error,
+ this);
+
+ if(!m_src)
+ {
+ // XXX printf("%s\n", src_strerror(error));
+ AUD_THROW(AUD_ERROR_SRC, state_error);
+ }
+ }
m_eos = false;
- length = src_callback_read(m_src, m_factor, length, buffer);
+ length = src_callback_read(m_src, factor, length, buffer);
m_position += length;
diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.h b/intern/audaspace/SRC/AUD_SRCResampleReader.h
index 5b210a61e70..896a742356b 100644
--- a/intern/audaspace/SRC/AUD_SRCResampleReader.h
+++ b/intern/audaspace/SRC/AUD_SRCResampleReader.h
@@ -44,24 +44,19 @@ class AUD_SRCResampleReader : public AUD_EffectReader
{
private:
/**
- * The sample specification of the source.
- */
- const AUD_Specs m_sspecs;
-
- /**
- * The resampling factor.
+ * The sound output buffer.
*/
- const double m_factor;
+ AUD_Buffer m_buffer;
/**
- * The sound output buffer.
+ * The target sampling rate.
*/
- AUD_Buffer m_buffer;
+ AUD_SampleRate m_rate;
/**
- * The target specification.
+ * The reader channels.
*/
- AUD_Specs m_tspecs;
+ AUD_Channels m_channels;
/**
* The src state structure.
diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp
index 404281a33bb..de23869441f 100644
--- a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp
+++ b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp
@@ -40,10 +40,5 @@ AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_Reference<AUD_IFactory>
AUD_Reference<AUD_IReader> AUD_LinearResampleFactory::createReader()
{
- AUD_Reference<AUD_IReader> reader = getReader();
-
- if(reader->getSpecs().rate != m_specs.rate)
- reader = new AUD_LinearResampleReader(reader, m_specs.specs);
-
- return reader;
+ return new AUD_LinearResampleReader(getReader(), m_specs.specs);
}
diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp
index 7e4f7a5b45d..c227baad73b 100644
--- a/intern/audaspace/intern/AUD_LinearResampleReader.cpp
+++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp
@@ -34,94 +34,140 @@
#include <cmath>
#include <cstring>
-#define CC channels + channel
+#define CC m_channels + channel
AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader,
AUD_Specs specs) :
AUD_EffectReader(reader),
- m_sspecs(reader->getSpecs()),
- m_factor(float(specs.rate) / float(m_sspecs.rate)),
- m_tspecs(specs),
+ m_rate(specs.rate),
+ m_channels(reader->getSpecs().channels),
m_position(0),
- m_sposition(0)
+ m_cache_pos(0),
+ m_cache_ok(false)
{
- m_tspecs.channels = m_sspecs.channels;
- m_cache.resize(2 * AUD_SAMPLE_SIZE(m_tspecs));
+ specs.channels = m_channels;
+ m_cache.resize(2 * AUD_SAMPLE_SIZE(specs));
}
void AUD_LinearResampleReader::seek(int position)
{
- m_position = position;
- m_sposition = floor(position / m_factor);
- m_reader->seek(m_sposition);
+ position = floor(position * double(m_reader->getSpecs().rate) / double(m_rate));
+ m_reader->seek(position);
+ m_cache_ok = false;
+ m_cache_pos = 0;
}
int AUD_LinearResampleReader::getLength() const
{
- return m_reader->getLength() * m_factor;
+ return floor(m_reader->getLength() * double(m_rate) / double(m_reader->getSpecs().rate));
}
int AUD_LinearResampleReader::getPosition() const
{
- return m_position;
+ return floor((m_reader->getPosition() + (m_cache_ok ? m_cache_pos - 2 : 0))
+ * m_rate / m_reader->getSpecs().rate);
}
AUD_Specs AUD_LinearResampleReader::getSpecs() const
{
- return m_tspecs;
+ AUD_Specs specs = m_reader->getSpecs();
+ specs.rate = m_rate;
+ return specs;
}
void AUD_LinearResampleReader::read(int& length, bool& eos, sample_t* buffer)
{
- int samplesize = AUD_SAMPLE_SIZE(m_tspecs);
+ AUD_Specs specs = m_reader->getSpecs();
+
+ int samplesize = AUD_SAMPLE_SIZE(specs);
int size = length;
+ float factor = float(m_rate) / float(m_reader->getSpecs().rate);
+ float spos;
+ sample_t low, high;
+ eos = false;
- m_buffer.assureSize(size * AUD_SAMPLE_SIZE(m_sspecs));
+ if(factor == 1 && (!m_cache_ok || m_cache_pos == 0))
+ {
+ // can read directly!
+ m_reader->read(length, eos, buffer);
+ return;
+ }
- int need = ceil((m_position + length) / m_factor) + 1 - m_sposition;
- int len = need;
- sample_t* buf = m_buffer.getBuffer();
+ // check for channels changed
- m_reader->read(len, eos, buf);
+ if(specs.channels != m_channels)
+ {
+ m_cache.resize(2 * samplesize);
+ m_channels = specs.channels;
+ m_cache_ok = false;
+ }
- if(len < need)
- length = floor((m_sposition + len - 1) * m_factor) - m_position;
+ int len;
+ sample_t* buf;
- float spos;
- sample_t low, high;
- int channels = m_sspecs.channels;
+ if(m_cache_ok)
+ {
+ int need = ceil(length / factor - (1 - m_cache_pos));
+
+ len = need;
+
+ m_buffer.assureSize((len + 3) * samplesize);
+ buf = m_buffer.getBuffer();
+
+ memcpy(buf, m_cache.getBuffer(), 2 * samplesize);
+ m_reader->read(len, eos, buf + 2 * m_channels);
- for(int channel = 0; channel < channels; channel++)
+ if(len < need)
+ length = floor((len + (1 - m_cache_pos)) * factor);
+ }
+ else
{
- for(int i = 0; i < length; i++)
- {
- spos = (m_position + i) / m_factor - m_sposition;
+ int need = ceil(length / factor) + 1;
+
+ len = need;
- if(floor(spos) < 0)
+ m_buffer.assureSize((len + 1) * samplesize);
+ buf = m_buffer.getBuffer();
+
+ m_reader->read(len, eos, buf);
+
+ if(len < need)
+ {
+ if(eos)
{
- low = m_cache.getBuffer()[(int)(floor(spos) + 2) * CC];
- if(ceil(spos) < 0)
- high = m_cache.getBuffer()[(int)(ceil(spos) + 2) * CC];
- else
- high = buf[(int)ceil(spos) * CC];
+ length = floor(len * factor);
+ memset(buf + len * m_channels, 0, samplesize);
}
else
- {
- low = buf[(int)floor(spos) * CC];
- high = buf[(int)ceil(spos) * CC];
- }
+ length = ceil((len - 1) * factor);
+ }
+ m_cache_ok = true;
+ m_cache_pos = 0;
+ }
+
+ for(int channel = 0; channel < m_channels; channel++)
+ {
+ for(int i = 0; i < length; i++)
+ {
+ spos = (i + 1) / factor + m_cache_pos;
+
+ low = buf[(int)floor(spos) * CC];
+ high = buf[(int)ceil(spos) * CC];
+
buffer[i * CC] = low + (spos - floor(spos)) * (high - low);
}
}
- if(len > 1)
- memcpy(m_cache.getBuffer(),
- buf + (len - 2) * channels,
- 2 * samplesize);
- else if(len == 1)
- memcpy(m_cache.getBuffer() + 1 * channels, buf, samplesize);
+ if(floor(spos) == spos)
+ {
+ memcpy(m_cache.getBuffer(), buf + int(floor(spos - 1)) * m_channels, 2 * samplesize);
+ m_cache_pos = 1;
+ }
+ else
+ {
+ memcpy(m_cache.getBuffer(), buf + int(floor(spos)) * m_channels, 2 * samplesize);
+ m_cache_pos = spos - floor(spos);
+ }
- m_sposition += len;
- m_position += length;
eos &= length < size;
}
diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.h b/intern/audaspace/intern/AUD_LinearResampleReader.h
index f7dd0e96aa6..8e0eac612fa 100644
--- a/intern/audaspace/intern/AUD_LinearResampleReader.h
+++ b/intern/audaspace/intern/AUD_LinearResampleReader.h
@@ -42,19 +42,14 @@ class AUD_LinearResampleReader : public AUD_EffectReader
{
private:
/**
- * The sample specification of the source.
- */
- const AUD_Specs m_sspecs;
-
- /**
- * The resampling factor.
+ * The target specification.
*/
- const float m_factor;
+ AUD_SampleRate m_rate;
/**
- * The target specification.
+ * The reader channels.
*/
- AUD_Specs m_tspecs;
+ AUD_Channels m_channels;
/**
* The current position.
@@ -62,9 +57,9 @@ private:
int m_position;
/**
- * The current reading source position.
+ * The position in the cache.
*/
- int m_sposition;
+ float m_cache_pos;
/**
* The sound output buffer.
@@ -76,6 +71,11 @@ private:
*/
AUD_Buffer m_cache;
+ /**
+ * Whether the cache contains valid data.
+ */
+ bool m_cache_ok;
+
// hide copy constructor and operator=
AUD_LinearResampleReader(const AUD_LinearResampleReader&);
AUD_LinearResampleReader& operator=(const AUD_LinearResampleReader&);