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>2010-02-08 02:41:17 +0300
committerJoerg Mueller <nexyon@gmail.com>2010-02-08 02:41:17 +0300
commit9827a3e9eac70f68db6dc16d03016c51b7ece3f0 (patch)
tree8825b454008d3b97a64018884c179ea94874af44 /intern
parent2f72b91a54faa7cfbdfd97eff608c8911df1d221 (diff)
2.5 Audio:
- recode of the whole sequencer audio handling - encode audio flag removed, instead you choose None as audio codec, added None for video codec too - ffmpeg formats/codecs: enabled: theora, ogg, vorbis; added: matroska, flac (not working, who can fix?), mp3, wav - sequencer wave drawing - volume animation (now also working when mixing down to a file!) - made sequencer strip position and length values unanimatable
Diffstat (limited to 'intern')
-rw-r--r--intern/audaspace/FX/AUD_LoopReader.cpp9
-rw-r--r--intern/audaspace/FX/AUD_LoopReader.h5
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.cpp13
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp109
-rw-r--r--intern/audaspace/intern/AUD_C-API.h29
-rw-r--r--intern/audaspace/intern/AUD_Mixer.cpp12
-rw-r--r--intern/audaspace/intern/AUD_Mixer.h9
-rw-r--r--intern/audaspace/intern/AUD_SequencerFactory.cpp109
-rw-r--r--intern/audaspace/intern/AUD_SequencerFactory.h77
-rw-r--r--intern/audaspace/intern/AUD_SequencerReader.cpp245
-rw-r--r--intern/audaspace/intern/AUD_SequencerReader.h102
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp9
-rw-r--r--intern/audaspace/intern/AUD_Space.h6
13 files changed, 707 insertions, 27 deletions
diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp
index 7d70fc20221..3bcd8c2f9d3 100644
--- a/intern/audaspace/FX/AUD_LoopReader.cpp
+++ b/intern/audaspace/FX/AUD_LoopReader.cpp
@@ -31,6 +31,7 @@
AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) :
AUD_EffectReader(reader), m_loop(loop)
{
+ m_samples = -1;
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
}
@@ -51,6 +52,7 @@ bool AUD_LoopReader::notify(AUD_Message &message)
if(message.type == AUD_MSG_LOOP)
{
m_loop = message.loopcount;
+ m_samples = message.time * m_reader->getSpecs().rate;
m_reader->notify(message);
@@ -64,6 +66,13 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
AUD_Specs specs = m_reader->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
+ if(m_samples >= 0)
+ {
+ if(length > m_samples)
+ length = m_samples;
+ m_samples -= length;
+ }
+
int len = length;
m_reader->read(len, buffer);
diff --git a/intern/audaspace/FX/AUD_LoopReader.h b/intern/audaspace/FX/AUD_LoopReader.h
index 621ee3493ab..e61a49cb0db 100644
--- a/intern/audaspace/FX/AUD_LoopReader.h
+++ b/intern/audaspace/FX/AUD_LoopReader.h
@@ -46,6 +46,11 @@ private:
*/
int m_loop;
+ /**
+ * The left samples.
+ */
+ int m_samples;
+
public:
/**
* Creates a new loop reader.
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
index 0b3e86eda56..9e153b9b34f 100644
--- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
@@ -180,7 +180,7 @@ void AUD_OpenALDevice::updateStreams()
AUD_DEVICE_SAMPLE_SIZE(specs),
specs.rate);
- if(alGetError() != AL_NO_ERROR)
+ if((err = alGetError()) != AL_NO_ERROR)
{
sound->data_end = true;
break;
@@ -839,13 +839,14 @@ bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
if(info != AL_PLAYING)
{
- if(info != AL_STOPPED)
+ if(info == AL_PAUSED)
alSourceStop(alhandle->source);
- alSourceUnqueueBuffers(alhandle->source,
- AUD_OPENAL_CYCLE_BUFFERS,
- alhandle->buffers);
- if(alGetError() == AL_NO_ERROR)
+ alSourcei(alhandle->source, AL_BUFFER, 0);
+ alhandle->current = 0;
+
+ ALenum err;
+ if((err = alGetError()) == AL_NO_ERROR)
{
sample_t* buf;
int length;
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index b7d0183cb5e..b363c4576b3 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -25,6 +25,7 @@
#include <cstdlib>
#include <cstring>
+#include <cmath>
#include "AUD_NULLDevice.h"
#include "AUD_I3DDevice.h"
@@ -47,6 +48,7 @@
#include "AUD_ReadDevice.h"
#include "AUD_SourceCaps.h"
#include "AUD_IReader.h"
+#include "AUD_SequencerFactory.h"
#ifdef WITH_SDL
#include "AUD_SDLDevice.h"
@@ -231,7 +233,7 @@ AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
}
}
-extern AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
+AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
{
assert(sound);
@@ -273,13 +275,14 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound)
}
}
-int AUD_stopLoop(AUD_Handle* handle)
+int AUD_setLoop(AUD_Handle* handle, int loops, float time)
{
if(handle)
{
AUD_Message message;
message.type = AUD_MSG_LOOP;
- message.loopcount = 0;
+ message.loopcount = loops;
+ message.time = time;
try
{
@@ -537,14 +540,16 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
}
}
-AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound)
+AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
{
assert(device);
assert(sound);
try
{
- return device->play(sound);
+ AUD_Handle* handle = device->play(sound);
+ device->seek(handle, seek);
+ return handle;
}
catch(AUD_Exception)
{
@@ -663,3 +668,97 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high,
*length = position;
return result;
}
+
+AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
+{
+ if(AUD_device)
+ {
+ return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
+ }
+ else
+ {
+ AUD_Specs specs;
+ specs.channels = AUD_CHANNELS_STEREO;
+ specs.rate = AUD_RATE_44100;
+ return new AUD_SequencerFactory(specs, data, volume);
+ }
+}
+
+void AUD_destroySequencer(AUD_Sound* sequencer)
+{
+ delete ((AUD_SequencerFactory*)sequencer);
+}
+
+AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
+ float begin, float end, float skip, void* data)
+{
+ return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data);
+}
+
+void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry)
+{
+ ((AUD_SequencerFactory*)sequencer)->remove(entry);
+}
+
+void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
+ float begin, float end, float skip)
+{
+ ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip);
+}
+
+void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute)
+{
+ ((AUD_SequencerFactory*)sequencer)->mute(entry, mute);
+}
+
+int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
+{
+ AUD_IReader* reader = sound->createReader();
+ AUD_DeviceSpecs specs;
+ sample_t* buf;
+
+ specs.specs = reader->getSpecs();
+ specs.channels = AUD_CHANNELS_MONO;
+ specs.format = AUD_FORMAT_FLOAT32;
+
+ AUD_ChannelMapperFactory mapper(reader, specs);
+
+ if(!reader || reader->getType() != AUD_TYPE_BUFFER)
+ return -1;
+
+ reader = mapper.createReader();
+
+ if(!reader)
+ return -1;
+
+ int len = reader->getLength();
+ float samplejump = (float)len / (float)length;
+ float min, max;
+
+ for(int i = 0; i < length; i++)
+ {
+ len = floor(samplejump * (i+1)) - floor(samplejump * i);
+ reader->read(len, buf);
+
+ if(len < 1)
+ {
+ length = i;
+ break;
+ }
+
+ max = min = *buf;
+ for(int j = 1; j < len; j++)
+ {
+ if(buf[j] < min)
+ min = buf[j];
+ if(buf[j] > max)
+ max = buf[j];
+ buffer[i * 2] = min;
+ buffer[i * 2 + 1] = max;
+ }
+ }
+
+ delete reader; AUD_DELETE("reader")
+
+ return length;
+}
diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h
index c3439f89ade..ce1791886de 100644
--- a/intern/audaspace/intern/AUD_C-API.h
+++ b/intern/audaspace/intern/AUD_C-API.h
@@ -50,6 +50,8 @@ typedef struct
typedef void AUD_Sound;
typedef void AUD_Handle;
typedef void AUD_Device;
+ typedef void AUD_SequencerEntry;
+ typedef float (*AUD_volumeFunction)(void*, void*, float);
#endif
/**
@@ -143,11 +145,13 @@ extern AUD_Sound* AUD_pingpongSound(AUD_Sound* sound);
extern AUD_Sound* AUD_loopSound(AUD_Sound* sound);
/**
- * Stops a looping sound when the current playback finishes.
+ * Sets a remaining loop count of a looping sound that currently plays.
* \param handle The playback handle.
+ * \param loops The count of remaining loops, -1 for infinity.
+ * \param time The time after which playback should stop, -1 for infinity.
* \return Whether the handle is valid.
*/
-extern int AUD_stopLoop(AUD_Handle* handle);
+extern int AUD_setLoop(AUD_Handle* handle, int loops, float time);
/**
* Rectifies a sound.
@@ -211,6 +215,7 @@ extern int AUD_seek(AUD_Handle* handle, float seekTo);
/**
* Retrieves the playback position of a handle.
+ * \param handle The handle to the sound.
* \return The current playback position in seconds or 0.0 if the handle is
* invalid.
*/
@@ -318,9 +323,10 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume);
* Plays back a sound file through a read device.
* \param device The read device.
* \param sound The handle of the sound file.
+ * \param seek The position where the sound should be seeked to.
* \return A handle to the played back sound.
*/
-extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound);
+extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
/**
* Sets the volume of a played back sound of a read device.
@@ -360,6 +366,23 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
float sthreshold, int samplerate,
int* length);
+extern AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume);
+
+extern void AUD_destroySequencer(AUD_Sound* sequencer);
+
+extern AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
+ float begin, float end, float skip, void* data);
+
+extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry);
+
+extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
+ float begin, float end, float skip);
+
+extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
+ char mute);
+
+extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/audaspace/intern/AUD_Mixer.cpp b/intern/audaspace/intern/AUD_Mixer.cpp
index bddc719b179..299388b558b 100644
--- a/intern/audaspace/intern/AUD_Mixer.cpp
+++ b/intern/audaspace/intern/AUD_Mixer.cpp
@@ -68,6 +68,11 @@ AUD_IReader* AUD_Mixer::prepare(AUD_IReader* reader)
return reader;
}
+AUD_DeviceSpecs AUD_Mixer::getSpecs()
+{
+ return m_specs;
+}
+
void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs)
{
m_specs = specs;
@@ -115,10 +120,11 @@ void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs)
}
}
-void AUD_Mixer::add(sample_t* buffer, int length, float volume)
+void AUD_Mixer::add(sample_t* buffer, int start, int length, float volume)
{
AUD_MixerBuffer buf;
buf.buffer = buffer;
+ buf.start = start;
buf.length = length;
buf.volume = volume;
m_buffers.push_back(buf);
@@ -145,11 +151,11 @@ void AUD_Mixer::superpose(data_t* buffer, int length, float volume)
buf = m_buffers.front();
m_buffers.pop_front();
- end = buf.length*channels;
+ end = buf.length * channels;
in = buf.buffer;
for(int i = 0; i < end; i++)
- out[i] += in[i]*buf.volume * volume;
+ out[i + buf.start * channels] += in[i] * buf.volume * volume;
}
m_convert(buffer, (data_t*) out, length * channels);
diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h
index 5097b9ec2a6..5dcdef45eba 100644
--- a/intern/audaspace/intern/AUD_Mixer.h
+++ b/intern/audaspace/intern/AUD_Mixer.h
@@ -37,6 +37,7 @@ class AUD_IReader;
struct AUD_MixerBuffer
{
sample_t* buffer;
+ int start;
int length;
float volume;
};
@@ -99,6 +100,12 @@ public:
AUD_IReader* prepare(AUD_IReader* reader);
/**
+ * Returns the target specification for superposing.
+ * \return The target specification.
+ */
+ AUD_DeviceSpecs getSpecs();
+
+ /**
* Sets the target specification for superposing.
* \param specs The target specification.
*/
@@ -111,7 +118,7 @@ public:
* \param length The length of the buffer in samples.
* \param volume The mixing volume. Must be a value between 0.0 and 1.0.
*/
- void add(sample_t* buffer, int length, float volume);
+ void add(sample_t* buffer, int start, int length, float volume);
/**
* Superposes all added buffers into an output buffer.
diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp
new file mode 100644
index 00000000000..bb5cf27fb5f
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp
@@ -0,0 +1,109 @@
+/*
+ * $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_SequencerFactory.h"
+#include "AUD_SequencerReader.h"
+
+typedef std::list<AUD_SequencerReader*>::iterator AUD_ReaderIterator;
+
+AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, void* data, AUD_volumeFunction volume)
+{
+ m_specs = specs;
+ m_data = data;
+ m_volume = volume;
+}
+
+AUD_SequencerFactory::~AUD_SequencerFactory()
+{
+ AUD_SequencerReader* reader;
+ AUD_SequencerEntry* entry;
+
+ while(!m_readers.empty())
+ {
+ reader = m_readers.front();
+ m_readers.pop_front();
+ reader->destroy();
+ }
+
+ while(!m_entries.empty())
+ {
+ entry = m_entries.front();
+ m_entries.pop_front();
+ delete entry; AUD_DELETE("seqentry")
+ }
+}
+
+AUD_SequencerEntry* AUD_SequencerFactory::add(AUD_IFactory** sound, float begin, float end, float skip, void* data)
+{
+ AUD_SequencerEntry* entry = new AUD_SequencerEntry; AUD_NEW("seqentry")
+ entry->sound = sound;
+ entry->begin = begin;
+ entry->skip = skip;
+ entry->end = end;
+ entry->muted = false;
+ entry->data = data;
+
+ m_entries.push_front(entry);
+
+ for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++)
+ (*i)->add(entry);
+
+ return entry;
+}
+
+void AUD_SequencerFactory::remove(AUD_SequencerEntry* entry)
+{
+ for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++)
+ (*i)->remove(entry);
+
+ m_entries.remove(entry);
+
+ delete entry; AUD_DELETE("seqentry")
+}
+
+void AUD_SequencerFactory::move(AUD_SequencerEntry* entry, float begin, float end, float skip)
+{
+ entry->begin = begin;
+ entry->skip = skip;
+ entry->end = end;
+}
+
+void AUD_SequencerFactory::mute(AUD_SequencerEntry* entry, bool mute)
+{
+ entry->muted = mute;
+}
+
+AUD_IReader* AUD_SequencerFactory::createReader()
+{
+ AUD_SequencerReader* reader = new AUD_SequencerReader(this, m_entries, m_specs, m_data, m_volume); AUD_NEW("reader")
+ m_readers.push_front(reader);
+
+ return reader;
+}
+
+void AUD_SequencerFactory::removeReader(AUD_SequencerReader* reader)
+{
+ m_readers.remove(reader);
+}
diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h
new file mode 100644
index 00000000000..b564c888fc6
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SequencerFactory.h
@@ -0,0 +1,77 @@
+/*
+ * $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 *****
+ */
+
+#ifndef AUD_SEQUENCERFACTORY
+#define AUD_SEQUENCERFACTORY
+
+#include "AUD_IFactory.h"
+
+#include <list>
+
+typedef float (*AUD_volumeFunction)(void*, void*, float);
+
+struct AUD_SequencerEntry
+{
+ AUD_IFactory** sound;
+ float begin;
+ float end;
+ float skip;
+ bool muted;
+ void* data;
+};
+
+class AUD_SequencerReader;
+
+/**
+ * This factory creates a resampling reader that does simple linear resampling.
+ */
+class AUD_SequencerFactory : public AUD_IFactory
+{
+private:
+ /**
+ * The target specification.
+ */
+ AUD_Specs m_specs;
+
+ std::list<AUD_SequencerEntry*> m_entries;
+ std::list<AUD_SequencerReader*> m_readers;
+ void* m_data;
+ AUD_volumeFunction m_volume;
+
+public:
+ AUD_SequencerFactory(AUD_Specs specs, void* data, AUD_volumeFunction volume);
+ ~AUD_SequencerFactory();
+
+ AUD_SequencerEntry* add(AUD_IFactory** sound, float begin, float end, float skip, void* data);
+ void remove(AUD_SequencerEntry* entry);
+ void move(AUD_SequencerEntry* entry, float begin, float end, float skip);
+ void mute(AUD_SequencerEntry* entry, bool mute);
+
+ virtual AUD_IReader* createReader();
+
+ void removeReader(AUD_SequencerReader* reader);
+};
+
+#endif //AUD_SEQUENCERFACTORY
diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp
new file mode 100644
index 00000000000..84c14762893
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SequencerReader.cpp
@@ -0,0 +1,245 @@
+/*
+ * $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_SequencerReader.h"
+#include "AUD_Buffer.h"
+
+#include <math.h>
+
+typedef std::list<AUD_SequencerStrip*>::iterator AUD_StripIterator;
+typedef std::list<AUD_SequencerEntry*>::iterator AUD_EntryIterator;
+
+AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, void* data, AUD_volumeFunction volume)
+{
+ AUD_DeviceSpecs dspecs;
+ dspecs.specs = specs;
+ dspecs.format = AUD_FORMAT_FLOAT32;
+
+ m_mixer.setSpecs(dspecs);
+ m_factory = factory;
+ m_data = data;
+ m_volume = volume;
+
+ AUD_SequencerStrip* strip;
+
+ for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++)
+ {
+ strip = new AUD_SequencerStrip; AUD_NEW("seqstrip")
+ strip->entry = *i;
+ strip->old_sound = NULL;
+
+ if(strip->old_sound)
+ strip->reader = m_mixer.prepare(strip->old_sound->createReader());
+ else
+ strip->reader = NULL;
+
+ m_strips.push_front(strip);
+ }
+
+ m_position = 0;
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_SequencerReader::~AUD_SequencerReader()
+{
+ if(m_factory != NULL)
+ m_factory->removeReader(this);
+
+ AUD_SequencerStrip* strip;
+
+ while(!m_strips.empty())
+ {
+ strip = m_strips.front();
+ m_strips.pop_front();
+ if(strip->reader)
+ {
+ delete strip->reader; AUD_DELETE("reader")
+ }
+ delete strip; AUD_DELETE("seqstrip")
+ }
+
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+void AUD_SequencerReader::destroy()
+{
+ m_factory = NULL;
+ AUD_SequencerStrip* strip;
+
+ while(!m_strips.empty())
+ {
+ strip = m_strips.front();
+ m_strips.pop_front();
+ delete strip; AUD_DELETE("seqstrip")
+ }
+}
+
+void AUD_SequencerReader::add(AUD_SequencerEntry* entry)
+{
+ AUD_SequencerStrip* strip = new AUD_SequencerStrip; AUD_NEW("seqstrip")
+ strip->entry = entry;
+ strip->old_sound = NULL;
+
+ if(strip->old_sound)
+ strip->reader = m_mixer.prepare(strip->old_sound->createReader());
+ else
+ strip->reader = NULL;
+
+ m_strips.push_front(strip);
+}
+
+void AUD_SequencerReader::remove(AUD_SequencerEntry* entry)
+{
+ AUD_SequencerStrip* strip;
+ for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
+ {
+ strip = *i;
+ if(strip->entry == entry)
+ {
+ i++;
+ if(strip->reader)
+ {
+ delete strip->reader; AUD_DELETE("reader")
+ }
+ m_strips.remove(strip);
+ delete strip;
+ return;
+ }
+ }
+}
+
+bool AUD_SequencerReader::isSeekable()
+{
+ return true;
+}
+
+void AUD_SequencerReader::seek(int position)
+{
+ m_position = position;
+}
+
+int AUD_SequencerReader::getLength()
+{
+ return -1;
+}
+
+int AUD_SequencerReader::getPosition()
+{
+ return m_position;
+}
+
+AUD_Specs AUD_SequencerReader::getSpecs()
+{
+ return m_mixer.getSpecs().specs;
+}
+
+AUD_ReaderType AUD_SequencerReader::getType()
+{
+ return AUD_TYPE_STREAM;
+}
+
+bool AUD_SequencerReader::notify(AUD_Message &message)
+{
+ bool result = false;
+ AUD_SequencerStrip* strip;
+
+ for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
+ {
+ strip = *i;
+ if(strip->reader)
+ result |= (*i)->reader->notify(message);
+ }
+
+ return result;
+}
+
+void AUD_SequencerReader::read(int & length, sample_t* & buffer)
+{
+ AUD_DeviceSpecs specs = m_mixer.getSpecs();
+ int samplesize = AUD_SAMPLE_SIZE(specs);
+ int rate = specs.rate;
+
+ int size = length * samplesize;
+
+ int start, end, current, skip, len;
+ AUD_SequencerStrip* strip;
+ sample_t* buf;
+
+ if(m_buffer->getSize() < size)
+ m_buffer->resize(size);
+ buffer = m_buffer->getBuffer();
+
+ for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
+ {
+ strip = *i;
+ if(!strip->entry->muted)
+ {
+ if(strip->old_sound != *strip->entry->sound)
+ {
+ strip->old_sound = *strip->entry->sound;
+ if(strip->reader)
+ {
+ delete strip->reader; AUD_DELETE("reader")
+ }
+
+ if(strip->old_sound)
+ strip->reader = m_mixer.prepare(strip->old_sound->createReader());
+ else
+ strip->reader = NULL;
+ }
+
+ if(strip->reader)
+ {
+ end = floor(strip->entry->end * rate);
+ if(m_position < end)
+ {
+ start = floor(strip->entry->begin * rate);
+ if(m_position + length > start)
+ {
+ current = m_position - start;
+ if(current < 0)
+ {
+ skip = -current;
+ current = 0;
+ }
+ else
+ skip = 0;
+ current += strip->entry->skip * rate;
+ len = length > end - m_position ? end - m_position : length;
+ len -= skip;
+ if(strip->reader->getPosition() != current)
+ strip->reader->seek(current);
+ strip->reader->read(len, buf);
+ m_mixer.add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
+ }
+ }
+ }
+ }
+ }
+
+ m_mixer.superpose((data_t*)buffer, length, 1.0f);
+
+ m_position += length;
+}
diff --git a/intern/audaspace/intern/AUD_SequencerReader.h b/intern/audaspace/intern/AUD_SequencerReader.h
new file mode 100644
index 00000000000..a50e1642260
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SequencerReader.h
@@ -0,0 +1,102 @@
+/*
+ * $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 *****
+ */
+
+#ifndef AUD_SEQUENCERREADER
+#define AUD_SEQUENCERREADER
+
+#include "AUD_IReader.h"
+#include "AUD_SequencerFactory.h"
+#include "AUD_Mixer.h"
+
+class AUD_Buffer;
+
+struct AUD_SequencerStrip
+{
+ AUD_IFactory* old_sound;
+ AUD_IReader* reader;
+ AUD_SequencerEntry* entry;
+};
+
+/**
+ * This resampling reader uses libsamplerate for resampling.
+ */
+class AUD_SequencerReader : public AUD_IReader
+{
+private:
+ /**
+ * The current position.
+ */
+ int m_position;
+
+ /**
+ * The sound output buffer.
+ */
+ AUD_Buffer *m_buffer;
+
+ /**
+ * The target specification.
+ */
+ AUD_Mixer m_mixer;
+
+ /**
+ * Saves the SequencerFactory the reader belongs to.
+ */
+ AUD_SequencerFactory* m_factory;
+
+ std::list<AUD_SequencerStrip*> m_strips;
+
+ void* m_data;
+ AUD_volumeFunction m_volume;
+
+public:
+ /**
+ * Creates a resampling reader.
+ * \param reader The reader to mix.
+ * \param specs The target specification.
+ * \exception AUD_Exception Thrown if the reader is NULL.
+ */
+ AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, void* data, AUD_volumeFunction volume);
+
+ /**
+ * Destroys the reader.
+ */
+ ~AUD_SequencerReader();
+
+ void destroy();
+
+ void add(AUD_SequencerEntry* entry);
+ void remove(AUD_SequencerEntry* entry);
+
+ virtual bool isSeekable();
+ virtual void seek(int position);
+ virtual int getLength();
+ virtual int getPosition();
+ virtual AUD_Specs getSpecs();
+ virtual AUD_ReaderType getType();
+ virtual bool notify(AUD_Message &message);
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_SEQUENCERREADER
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index a615bcd0245..5a3f25fba07 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -100,7 +100,6 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
AUD_SoftwareHandle* sound;
int len;
sample_t* buf;
- int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs);
std::list<AUD_SoftwareHandle*> stopSounds;
// for all sounds
@@ -116,7 +115,7 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
len = length;
sound->reader->read(len, buf);
- m_mixer->add(buf, len, sound->volume);
+ m_mixer->add(buf, 0, len, sound->volume);
// in case the end of the sound is reached
if(len < length)
@@ -128,12 +127,6 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
}
}
- // fill with silence
- if(m_specs.format == AUD_FORMAT_U8)
- memset(buffer, 0x80, length * sample_size);
- else
- memset(buffer, 0, length * sample_size);
-
// superpose
m_mixer->superpose(buffer, length, m_volume);
diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h
index 1d60be3979b..9e192ac2cac 100644
--- a/intern/audaspace/intern/AUD_Space.h
+++ b/intern/audaspace/intern/AUD_Space.h
@@ -294,7 +294,11 @@ typedef struct
union
{
// loop reader
- int loopcount;
+ struct
+ {
+ int loopcount;
+ float time;
+ };
// volume reader
float volume;