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-21 21:01:41 +0300
committerJoerg Mueller <nexyon@gmail.com>2010-02-21 21:01:41 +0300
commit38ef2df8f72fe3289beb42284b1f2f3162636519 (patch)
tree6109eccb897749f050d78de1e8e581c3dd360aa1 /intern
parentee12a5368a0018467bb34292f3e4f063592dc830 (diff)
2.5 Audio:
* Jack Transport support! * Minor sequencer audio corrections.
Diffstat (limited to 'intern')
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp63
-rw-r--r--intern/audaspace/intern/AUD_C-API.h13
-rw-r--r--intern/audaspace/jack/AUD_JackDevice.cpp161
-rw-r--r--intern/audaspace/jack/AUD_JackDevice.h45
4 files changed, 244 insertions, 38 deletions
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index 3c29b5d9e08..d2540d59eda 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -761,6 +761,69 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
return length;
}
+void AUD_startPlayback()
+{
+#ifdef WITH_JACK
+ AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+ if(device)
+ device->startPlayback();
+#endif
+}
+
+void AUD_stopPlayback()
+{
+#ifdef WITH_JACK
+ AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+ if(device)
+ device->stopPlayback();
+#endif
+}
+
+void AUD_seekSequencer(AUD_Handle* handle, float time)
+{
+#ifdef WITH_JACK
+ AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+ if(device)
+ device->seekPlayback(time);
+ else
+#endif
+ {
+ AUD_device->seek(handle, time);
+ }
+}
+
+float AUD_getSequencerPosition(AUD_Handle* handle)
+{
+#ifdef WITH_JACK
+ AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+ if(device)
+ return device->getPlaybackPosition();
+ else
+#endif
+ {
+ return AUD_device->getPosition(handle);
+ }
+}
+
+void AUD_setSyncCallback(AUD_syncFunction function, void* data)
+{
+#ifdef WITH_JACK
+ AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+ if(device)
+ device->setSyncCallback(function, data);
+#endif
+}
+
+int AUD_doesPlayback()
+{
+#ifdef WITH_JACK
+ AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
+ if(device)
+ return device->doesPlayback();
+#endif
+ return -1;
+}
+
#ifdef AUD_DEBUG_MEMORY
int AUD_References(int count, const char* text)
{
diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h
index ce1791886de..a252ad904b6 100644
--- a/intern/audaspace/intern/AUD_C-API.h
+++ b/intern/audaspace/intern/AUD_C-API.h
@@ -52,6 +52,7 @@ typedef struct
typedef void AUD_Device;
typedef void AUD_SequencerEntry;
typedef float (*AUD_volumeFunction)(void*, void*, float);
+ typedef void (*AUD_syncFunction)(void*, int, float);
#endif
/**
@@ -383,6 +384,18 @@ extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
+extern void AUD_startPlayback();
+
+extern void AUD_stopPlayback();
+
+extern void AUD_seekSequencer(AUD_Handle* handle, float time);
+
+extern float AUD_getSequencerPosition(AUD_Handle* handle);
+
+extern void AUD_setSyncCallback(AUD_syncFunction function, void* data);
+
+extern int AUD_doesPlayback();
+
#ifdef __cplusplus
}
#endif
diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp
index dfb2a60d629..ae7725be81c 100644
--- a/intern/audaspace/jack/AUD_JackDevice.cpp
+++ b/intern/audaspace/jack/AUD_JackDevice.cpp
@@ -31,7 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
-void* AUD_JackDevice::runThread(void* device)
+void* AUD_JackDevice::runMixingThread(void* device)
{
((AUD_JackDevice*)device)->updateRingBuffers();
return NULL;
@@ -45,10 +45,24 @@ void AUD_JackDevice::updateRingBuffers()
unsigned int channels = m_specs.channels;
sample_t* buffer = m_buffer->getBuffer();
float* deinterleave = m_deinterleavebuf->getBuffer();
+ jack_transport_state_t state;
+ jack_position_t position;
- pthread_mutex_lock(&m_lock);
+ pthread_mutex_lock(&m_mixingLock);
while(m_valid)
{
+ if(m_sync > 1)
+ {
+ if(m_syncFunc)
+ {
+ state = jack_transport_query(m_client, &position);
+ m_syncFunc(m_syncFuncData, state != JackTransportStopped, position.frame / (float) m_specs.rate);
+ }
+
+ for(i = 0; i < channels; i++)
+ jack_ringbuffer_reset(m_ringbuffers[i]);
+ }
+
size = jack_ringbuffer_write_space(m_ringbuffers[0]);
for(i = 1; i < channels; i++)
if((temp = jack_ringbuffer_write_space(m_ringbuffers[i])) < size)
@@ -71,9 +85,14 @@ void AUD_JackDevice::updateRingBuffers()
size = temp;
}
- pthread_cond_wait(&m_condition, &m_lock);
+ if(m_sync > 1)
+ {
+ m_sync = 3;
+ }
+
+ pthread_cond_wait(&m_mixingCondition, &m_mixingLock);
}
- pthread_mutex_unlock(&m_lock);
+ pthread_mutex_unlock(&m_mixingLock);
}
int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
@@ -83,27 +102,67 @@ int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
int count = device->m_specs.channels;
char* buffer;
- size_t temp;
- size_t readsamples = jack_ringbuffer_read_space(device->m_ringbuffers[0]);
- for(i = 1; i < count; i++)
- if((temp = jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
- readsamples = temp;
+ if(device->m_sync)
+ {
+ // play silence while syncing
+ for(unsigned int i = 0; i < count; i++)
+ memset(jack_port_get_buffer(device->m_ports[i], length), 0, length * sizeof(float));
+ }
+ else
+ {
+ size_t temp;
+ size_t readsamples = jack_ringbuffer_read_space(device->m_ringbuffers[0]);
+ for(i = 1; i < count; i++)
+ if((temp = jack_ringbuffer_read_space(device->m_ringbuffers[i])) < readsamples)
+ readsamples = temp;
- readsamples = AUD_MIN(readsamples / sizeof(float), length);
+ readsamples = AUD_MIN(readsamples / sizeof(float), length);
- for(unsigned int i = 0; i < count; i++)
- {
- buffer = (char*)jack_port_get_buffer(device->m_ports[i], length);
- jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
- if(readsamples < length)
- memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float));
+ for(unsigned int i = 0; i < count; i++)
+ {
+ buffer = (char*)jack_port_get_buffer(device->m_ports[i], length);
+ jack_ringbuffer_read(device->m_ringbuffers[i], buffer, readsamples * sizeof(float));
+ if(readsamples < length)
+ memset(buffer + readsamples * sizeof(float), 0, (length - readsamples) * sizeof(float));
+ }
+
+ if(pthread_mutex_trylock(&(device->m_mixingLock)) == 0)
+ {
+ pthread_cond_signal(&(device->m_mixingCondition));
+ pthread_mutex_unlock(&(device->m_mixingLock));
+ }
}
- if(pthread_mutex_trylock(&(device->m_lock)) == 0)
+ return 0;
+}
+
+int AUD_JackDevice::jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data)
+{
+ AUD_JackDevice* device = (AUD_JackDevice*)data;
+
+ if(state == JackTransportStopped)
+ return 1;
+
+ if(pthread_mutex_trylock(&(device->m_mixingLock)) == 0)
{
- pthread_cond_signal(&(device->m_condition));
- pthread_mutex_unlock(&(device->m_lock));
+ if(device->m_sync > 2)
+ {
+ if(device->m_sync == 3)
+ {
+ device->m_sync = 0;
+ pthread_mutex_unlock(&(device->m_mixingLock));
+ return 1;
+ }
+ }
+ else
+ {
+ device->m_sync = 2;
+ pthread_cond_signal(&(device->m_mixingCondition));
+ }
+ pthread_mutex_unlock(&(device->m_mixingLock));
}
+ else if(!device->m_sync)
+ device->m_sync = 1;
return 0;
}
@@ -134,6 +193,7 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
// set callbacks
jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this);
jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this);
+ jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this);
// register our output channels which are called ports in jack
m_ports = new jack_port_t*[m_specs.channels]; AUD_NEW("jack_port")
@@ -170,6 +230,14 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
create();
+ m_valid = true;
+ m_playing = false;
+ m_sync = 0;
+ m_syncFunc = NULL;
+
+ pthread_mutex_init(&m_mixingLock, NULL);
+ pthread_cond_init(&m_mixingCondition, NULL);
+
try
{
// activate the client
@@ -185,6 +253,8 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
for(unsigned int i = 0; i < specs.channels; i++)
jack_ringbuffer_free(m_ringbuffers[i]);
delete[] m_ringbuffers; AUD_DELETE("jack_buffers")
+ pthread_mutex_destroy(&m_mixingLock);
+ pthread_cond_destroy(&m_mixingCondition);
destroy();
throw;
}
@@ -199,16 +269,11 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
free(ports);
}
- m_valid = true;
-
- pthread_mutex_init(&m_lock, NULL);
- pthread_cond_init(&m_condition, NULL);
-
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- pthread_create(&m_thread, &attr, runThread, this);
+ pthread_create(&m_mixingThread, &attr, runMixingThread, this);
pthread_attr_destroy(&attr);
}
@@ -221,13 +286,13 @@ AUD_JackDevice::~AUD_JackDevice()
delete[] m_ports; AUD_DELETE("jack_port")
- pthread_mutex_lock(&m_lock);
- pthread_cond_signal(&m_condition);
- pthread_mutex_unlock(&m_lock);
- pthread_join(m_thread, NULL);
+ pthread_mutex_lock(&m_mixingLock);
+ pthread_cond_signal(&m_mixingCondition);
+ pthread_mutex_unlock(&m_mixingLock);
+ pthread_join(m_mixingThread, NULL);
- pthread_cond_destroy(&m_condition);
- pthread_mutex_destroy(&m_lock);
+ pthread_cond_destroy(&m_mixingCondition);
+ pthread_mutex_destroy(&m_mixingLock);
delete m_buffer; AUD_DELETE("buffer");
delete m_deinterleavebuf; AUD_DELETE("buffer");
for(unsigned int i = 0; i < m_specs.channels; i++)
@@ -241,3 +306,37 @@ void AUD_JackDevice::playing(bool playing)
{
// Do nothing.
}
+
+void AUD_JackDevice::startPlayback()
+{
+ jack_transport_start(m_client);
+}
+
+void AUD_JackDevice::stopPlayback()
+{
+ jack_transport_stop(m_client);
+}
+
+void AUD_JackDevice::seekPlayback(float time)
+{
+ if(time >= 0.0f)
+ jack_transport_locate(m_client, time * m_specs.rate);
+}
+
+void AUD_JackDevice::setSyncCallback(AUD_syncFunction sync, void* data)
+{
+ m_syncFunc = sync;
+ m_syncFuncData = data;
+}
+
+float AUD_JackDevice::getPlaybackPosition()
+{
+ jack_position_t position;
+ jack_transport_query(m_client, &position);
+ return position.frame / (float) m_specs.rate;
+}
+
+bool AUD_JackDevice::doesPlayback()
+{
+ return jack_transport_query(m_client, NULL) != JackTransportStopped;
+}
diff --git a/intern/audaspace/jack/AUD_JackDevice.h b/intern/audaspace/jack/AUD_JackDevice.h
index 96388e1ee50..58e34978c1f 100644
--- a/intern/audaspace/jack/AUD_JackDevice.h
+++ b/intern/audaspace/jack/AUD_JackDevice.h
@@ -33,6 +33,8 @@ class AUD_Buffer;
#include <jack.h>
#include <ringbuffer.h>
+typedef void (*AUD_syncFunction)(void*, int, float);
+
/**
* This device plays back through Jack.
*/
@@ -56,6 +58,8 @@ private:
AUD_Buffer* m_deinterleavebuf;
+ jack_ringbuffer_t** m_ringbuffers;
+
/**
* Whether the device is valid.
*/
@@ -75,20 +79,40 @@ private:
*/
static int jack_mix(jack_nframes_t length, void *data);
- static void* runThread(void* device);
+ static int jack_sync(jack_transport_state_t state, jack_position_t* pos, void* data);
- void updateRingBuffers();
+ /**
+ * Last Jack Transport playing state.
+ */
+ bool m_playing;
- jack_ringbuffer_t** m_ringbuffers;
+ /**
+ * Syncronisation state.
+ */
+ int m_sync;
/**
- * The streaming thread.
+ * External syncronisation callback function.
*/
- pthread_t m_thread;
+ AUD_syncFunction m_syncFunc;
- pthread_mutex_t m_lock;
+ /**
+ * Data for the sync function.
+ */
+ void* m_syncFuncData;
+
+ /**
+ * The mixing thread.
+ */
+ pthread_t m_mixingThread;
+
+ pthread_mutex_t m_mixingLock;
- pthread_cond_t m_condition;
+ pthread_cond_t m_mixingCondition;
+
+ static void* runMixingThread(void* device);
+
+ void updateRingBuffers();
protected:
virtual void playing(bool playing);
@@ -105,6 +129,13 @@ public:
* Closes the Jack client.
*/
virtual ~AUD_JackDevice();
+
+ void startPlayback();
+ void stopPlayback();
+ void seekPlayback(float time);
+ void setSyncCallback(AUD_syncFunction sync, void* data);
+ float getPlaybackPosition();
+ bool doesPlayback();
};
#endif //AUD_JACKDEVICE