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>2009-08-16 18:53:11 +0400
committerJoerg Mueller <nexyon@gmail.com>2009-08-16 18:53:11 +0400
commit1ee26d45b58c4544c25899763e83ec06349ad780 (patch)
treec71e27b732e296e06e1f5cc8159614f7635c8876 /intern/audaspace
parentf250a92808a10f81abef1459223dbb5be40753b8 (diff)
Added jack audio support, building with cmake only currently, feel free to add scons and maybe cmake.
Diffstat (limited to 'intern/audaspace')
-rw-r--r--intern/audaspace/CMakeLists.txt8
-rw-r--r--intern/audaspace/SDL/AUD_SDLDevice.cpp15
-rw-r--r--intern/audaspace/SDL/AUD_SDLDevice.h19
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp2
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp16
-rw-r--r--intern/audaspace/intern/AUD_C-API.h3
-rw-r--r--intern/audaspace/intern/AUD_Space.h3
-rw-r--r--intern/audaspace/jack/AUD_JackDevice.cpp149
-rw-r--r--intern/audaspace/jack/AUD_JackDevice.h91
9 files changed, 279 insertions, 27 deletions
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt
index 4939e1d38d9..940a4b2bedc 100644
--- a/intern/audaspace/CMakeLists.txt
+++ b/intern/audaspace/CMakeLists.txt
@@ -47,6 +47,12 @@ IF(WITH_OPENAL)
ENDIF(FRAMEWORK)
ENDIF(WITH_OPENAL)
-SET(SRC ${SRC} ${FFMPEGSRC} ${SDLSRC} ${OPENALSRC})
+IF(WITH_JACK)
+ SET(INC ${INC} jack ${JACK_INC})
+ FILE(GLOB JACKSRC jack/*.cpp)
+ ADD_DEFINITIONS(-DWITH_JACK)
+ENDIF(WITH_JACK)
+
+SET(SRC ${SRC} ${FFMPEGSRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC})
BLENDERLIB(bf_audaspace "${SRC}" "${INC}")
diff --git a/intern/audaspace/SDL/AUD_SDLDevice.cpp b/intern/audaspace/SDL/AUD_SDLDevice.cpp
index 9ea5f1a74ee..dd443e7f5c7 100644
--- a/intern/audaspace/SDL/AUD_SDLDevice.cpp
+++ b/intern/audaspace/SDL/AUD_SDLDevice.cpp
@@ -27,13 +27,11 @@
#include "AUD_SDLDevice.h"
#include "AUD_IReader.h"
-#include <SDL.h>
-
-// this is the callback function for SDL, it only calls the class
-void mixAudio(void *data, Uint8* buffer, int length)
+void AUD_SDLDevice::SDL_mix(void *data, Uint8* buffer, int length)
{
AUD_SDLDevice* device = (AUD_SDLDevice*)data;
- device->SDLmix((sample_t *)buffer, length);
+
+ device->mix((sample_t*)buffer, length/AUD_SAMPLE_SIZE(device->m_specs));
}
AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize)
@@ -56,7 +54,7 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize)
format.format = AUDIO_S16SYS;
format.channels = m_specs.channels;
format.samples = buffersize;
- format.callback = &mixAudio;
+ format.callback = AUD_SDLDevice::SDL_mix;
format.userdata = this;
if(SDL_OpenAudio(&format, &obtained) != 0)
@@ -86,11 +84,6 @@ AUD_SDLDevice::~AUD_SDLDevice()
destroy();
}
-void AUD_SDLDevice::SDLmix(sample_t* buffer, int length)
-{
- mix(buffer, length/AUD_SAMPLE_SIZE(m_specs));
-}
-
void AUD_SDLDevice::playing(bool playing)
{
SDL_PauseAudio(playing ? 0 : 1);
diff --git a/intern/audaspace/SDL/AUD_SDLDevice.h b/intern/audaspace/SDL/AUD_SDLDevice.h
index 3eb93d28762..e2c6f7631b7 100644
--- a/intern/audaspace/SDL/AUD_SDLDevice.h
+++ b/intern/audaspace/SDL/AUD_SDLDevice.h
@@ -28,11 +28,22 @@
#include "AUD_SoftwareDevice.h"
+#include <SDL.h>
+
/**
* This device plays back through SDL, the simple direct media layer.
*/
class AUD_SDLDevice : public AUD_SoftwareDevice
{
+private:
+ /**
+ * Mixes the next bytes into the buffer.
+ * \param data The SDL device.
+ * \param buffer The target buffer.
+ * \param length The length in bytes to be filled.
+ */
+ static void SDL_mix(void *data, Uint8* buffer, int length);
+
protected:
virtual void playing(bool playing);
@@ -50,14 +61,6 @@ public:
* Closes the SDL audio device.
*/
virtual ~AUD_SDLDevice();
-
- /**
- * Mixes the next bytes into the buffer.
- * \param buffer The target buffer.
- * \param length The length in bytes to be filled.
- * \warning This function shall not be called from outside!
- */
- void SDLmix(sample_t* buffer, int length);
};
#endif //AUD_SDLDEVICE
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
index 28356e3b97d..b79375c2dc5 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
@@ -34,7 +34,7 @@ extern "C" {
#include <libavformat/avformat.h>
}
-// This function transforms a FFMPEG SampleFormat to or own sample format
+// This function transforms a FFMPEG SampleFormat to our own sample format
static inline AUD_SampleFormat FFMPEG_TO_AUD(SampleFormat fmt)
{
switch(fmt)
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index 92a499e84b8..d2c8e94c949 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -23,10 +23,6 @@
* ***** END LGPL LICENSE BLOCK *****
*/
-/*#define WITH_SDL
-#define WITH_FFMPEG
-#define WITH_OPENAL*/
-
#include "AUD_NULLDevice.h"
#include "AUD_I3DDevice.h"
#include "AUD_StreamBufferFactory.h"
@@ -47,6 +43,10 @@
#include "AUD_OpenALDevice.h"
#endif
+#ifdef WITH_JACK
+#include "AUD_JackDevice.h"
+#endif
+
#ifdef WITH_FFMPEG
#include "AUD_FFMPEGFactory.h"
extern "C" {
@@ -98,6 +98,11 @@ int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize)
dev = new AUD_OpenALDevice(specs, buffersize);
break;
#endif
+#ifdef WITH_JACK
+ case AUD_JACK_DEVICE:
+ dev = new AUD_JackDevice(specs);
+ break;
+#endif
default:
return false;
}
@@ -126,6 +131,9 @@ int* AUD_enumDevices()
#ifdef WITH_OPENAL
AUD_available_devices[i++] = AUD_OPENAL_DEVICE;
#endif
+#ifdef WITH_JACK
+ AUD_available_devices[i++] = AUD_JACK_DEVICE;
+#endif
AUD_available_devices[i++] = AUD_NULL_DEVICE;
return AUD_available_devices;
}
diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h
index b08f05db1ca..6ec5ec87ad5 100644
--- a/intern/audaspace/intern/AUD_C-API.h
+++ b/intern/audaspace/intern/AUD_C-API.h
@@ -36,7 +36,8 @@ typedef enum
{
AUD_NULL_DEVICE = 0,
AUD_SDL_DEVICE,
- AUD_OPENAL_DEVICE
+ AUD_OPENAL_DEVICE,
+ AUD_JACK_DEVICE
} AUD_DeviceType;
typedef struct
diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h
index 9c6cc70c314..123d9c272a0 100644
--- a/intern/audaspace/intern/AUD_Space.h
+++ b/intern/audaspace/intern/AUD_Space.h
@@ -180,7 +180,8 @@ typedef enum
AUD_ERROR_FILE,
AUD_ERROR_FFMPEG,
AUD_ERROR_SDL,
- AUD_ERROR_OPENAL
+ AUD_ERROR_OPENAL,
+ AUD_ERROR_JACK
} AUD_Error;
/// Message codes.
diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp
new file mode 100644
index 00000000000..02095caab74
--- /dev/null
+++ b/intern/audaspace/jack/AUD_JackDevice.cpp
@@ -0,0 +1,149 @@
+/*
+ * $Id: AUD_SDLDevice.cpp 22328 2009-08-09 23:23:19Z gsrb3d $
+ *
+ * ***** 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_FloatMixer.h"
+#include "AUD_JackDevice.h"
+#include "AUD_IReader.h"
+#include "AUD_Buffer.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+// AUD_XXX this is not realtime suitable!
+int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
+{
+ AUD_JackDevice* device = (AUD_JackDevice*)data;
+ int samplesize = AUD_SAMPLE_SIZE(device->m_specs);
+ if(device->m_buffer->getSize() < samplesize * length)
+ device->m_buffer->resize(samplesize * length);
+ device->mix(device->m_buffer->getBuffer(), length);
+
+ float* in = (float*) device->m_buffer->getBuffer();
+ float* out;
+ int count = device->m_specs.channels;
+
+ for(int i = 0; i < count; i++)
+ {
+ out = (float*)jack_port_get_buffer(device->m_ports[i], length);
+ for(int j = 0; j < length; j++)
+ out[j] = in[j * count + i];
+ }
+
+ return 0;
+}
+
+void AUD_JackDevice::jack_shutdown(void *data)
+{
+ AUD_JackDevice* device = (AUD_JackDevice*)data;
+ device->m_valid = false;
+}
+
+AUD_JackDevice::AUD_JackDevice(AUD_Specs specs)
+{
+ if(specs.channels == AUD_CHANNELS_INVALID)
+ specs.channels = AUD_CHANNELS_STEREO;
+
+ // jack uses floats
+ m_specs = specs;
+ m_specs.format = AUD_FORMAT_FLOAT32;
+
+ jack_options_t options = JackNullOption;
+ jack_status_t status;
+
+ // open client
+ m_client = jack_client_open("Blender", options, &status);
+ if(m_client == NULL)
+ AUD_THROW(AUD_ERROR_JACK);
+
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer");
+
+ // set callbacks
+ jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this);
+ jack_on_shutdown(m_client, AUD_JackDevice::jack_shutdown, this);
+
+ // register our output channels which are called ports in jack
+ m_ports = new jack_port_t*[m_specs.channels]; AUD_NEW("jack_port")
+
+ try
+ {
+ char portname[64];
+ for(int i = 0; i < m_specs.channels; i++)
+ {
+ sprintf(portname, "out %d", i+1);
+ m_ports[i] = jack_port_register(m_client, portname,
+ JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsOutput, 0);
+ if(m_ports[i] == NULL)
+ AUD_THROW(AUD_ERROR_JACK);
+ }
+
+ m_specs.rate = (AUD_SampleRate)jack_get_sample_rate(m_client);
+
+ // activate the client
+ if(jack_activate(m_client))
+ AUD_THROW(AUD_ERROR_JACK);
+ }
+ catch(AUD_Exception e)
+ {
+ jack_client_close(m_client);
+ delete[] m_ports; AUD_DELETE("jack_port")
+ delete m_buffer; AUD_DELETE("buffer");
+ throw;
+ }
+
+ const char** ports = jack_get_ports(m_client, NULL, NULL,
+ JackPortIsPhysical | JackPortIsInput);
+ if(ports != NULL)
+ {
+ for(int i = 0; i < m_specs.channels && ports[i]; i++)
+ jack_connect(m_client, jack_port_name(m_ports[i]), ports[i]);
+
+ free(ports);
+ }
+
+ m_mixer = new AUD_FloatMixer(); AUD_NEW("mixer")
+ m_mixer->setSpecs(m_specs);
+
+ m_valid = true;
+
+ create();
+}
+
+AUD_JackDevice::~AUD_JackDevice()
+{
+ lock();
+ if(m_valid)
+ jack_client_close(m_client);
+ delete[] m_ports; AUD_DELETE("jack_port")
+ delete m_buffer; AUD_DELETE("buffer");
+ unlock();
+
+ destroy();
+}
+
+void AUD_JackDevice::playing(bool playing)
+{
+ // Do nothing.
+}
diff --git a/intern/audaspace/jack/AUD_JackDevice.h b/intern/audaspace/jack/AUD_JackDevice.h
new file mode 100644
index 00000000000..7b340992d52
--- /dev/null
+++ b/intern/audaspace/jack/AUD_JackDevice.h
@@ -0,0 +1,91 @@
+/*
+ * $Id: AUD_SDLDevice.h 22328 2009-08-09 23:23:19Z gsrb3d $
+ *
+ * ***** 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_JACKDEVICE
+#define AUD_JACKDEVICE
+
+#include "AUD_SoftwareDevice.h"
+class AUD_Buffer;
+
+#include <jack.h>
+
+/**
+ * This device plays back through Jack.
+ */
+class AUD_JackDevice : public AUD_SoftwareDevice
+{
+private:
+ /**
+ * The output ports of jack.
+ */
+ jack_port_t** m_ports;
+
+ /**
+ * The jack client.
+ */
+ jack_client_t* m_client;
+
+ /**
+ * The output buffer.
+ */
+ AUD_Buffer* m_buffer;
+
+ /**
+ * Whether the device is valid.
+ */
+ bool m_valid;
+
+ /**
+ * Invalidates the jack device.
+ * \param data The jack device that gets invalidet by jack.
+ */
+ static void jack_shutdown(void *data);
+
+ /**
+ * Mixes the next bytes into the buffer.
+ * \param length The length in samples to be filled.
+ * \param data A pointer to the jack device.
+ * \return 0 what shows success.
+ */
+ static int jack_mix(jack_nframes_t length, void *data);
+
+protected:
+ virtual void playing(bool playing);
+
+public:
+ /**
+ * Creates a Jack client for audio output.
+ * \param specs The wanted audio specification, where only the channel count is important.
+ * \exception AUD_Exception Thrown if the audio device cannot be opened.
+ */
+ AUD_JackDevice(AUD_Specs specs);
+
+ /**
+ * Closes the Jack client.
+ */
+ virtual ~AUD_JackDevice();
+};
+
+#endif //AUD_JACKDEVICE