Added jack audio support, building with cmake only currently, feel free to add scons and maybe cmake.
This commit is contained in:
@@ -54,6 +54,9 @@ MACRO(SETUP_LIBDIRS)
|
||||
IF(WITH_OPENAL)
|
||||
LINK_DIRECTORIES(${OPENAL_LIBPATH})
|
||||
ENDIF(WITH_OPENAL)
|
||||
IF(WITH_JACK)
|
||||
LINK_DIRECTORIES(${JACK_LIBPATH})
|
||||
ENDIF(WITH_JACK)
|
||||
IF(WITH_FFTW3)
|
||||
LINK_DIRECTORIES(${FFTW3_LIBPATH})
|
||||
ENDIF(WITH_FFTW3)
|
||||
@@ -108,6 +111,9 @@ MACRO(SETUP_LIBLINKS
|
||||
IF(WITH_OPENAL)
|
||||
TARGET_LINK_LIBRARIES(${target} ${OPENAL_LIBRARY})
|
||||
ENDIF(WITH_OPENAL)
|
||||
IF(WITH_JACK)
|
||||
TARGET_LINK_LIBRARIES(${target} ${JACK_LIB})
|
||||
ENDIF(WITH_JACK)
|
||||
IF(WITH_SDL)
|
||||
TARGET_LINK_LIBRARIES(${target} ${SDL_LIBRARY})
|
||||
ENDIF(WITH_SDL)
|
||||
|
@@ -69,6 +69,7 @@ OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON)
|
||||
OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF)
|
||||
OPTION(WITH_WEBPLUGIN "Enable Web Plugin (Unix only)" OFF)
|
||||
OPTION(WITH_FFTW3 "Enable FFTW3 support" OFF)
|
||||
OPTION(WITH_JACK "Enable Jack Support (http://www.jackaudio.org)" OFF)
|
||||
OPTION(WITH_INSTALL "Install accompanying scripts and language files needed to run blender" ON)
|
||||
|
||||
IF(NOT WITH_GAMEENGINE AND WITH_PLAYER)
|
||||
@@ -100,6 +101,13 @@ IF(UNIX AND NOT APPLE)
|
||||
ENDIF(OPENAL_FOUND)
|
||||
ENDIF(WITH_OPENAL)
|
||||
|
||||
IF(WITH_JACK)
|
||||
SET(JACK /usr)
|
||||
SET(JACK_INC ${JACK}/include/jack)
|
||||
SET(JACK_LIB jack)
|
||||
SET(JACK_LIBPATH ${JACK}/lib)
|
||||
ENDIF(WITH_JACK)
|
||||
|
||||
FIND_LIBRARY(INTL_LIBRARY
|
||||
NAMES intl
|
||||
PATHS
|
||||
@@ -230,6 +238,13 @@ IF(WIN32)
|
||||
SET(OPENAL_LIBPATH ${OPENAL}/lib)
|
||||
ENDIF(CMAKE_CL_64)
|
||||
|
||||
IF(WITH_JACK)
|
||||
SET(JACK ${LIBDIR}/jack)
|
||||
SET(JACK_INC ${JACK}/include/jack)
|
||||
SET(JACK_LIB jack)
|
||||
SET(JACK_LIBPATH ${JACK}/lib)
|
||||
ENDIF(WITH_JACK)
|
||||
|
||||
IF(CMAKE_CL_64)
|
||||
SET(PNG_LIBRARIES libpng)
|
||||
ELSE(CMAKE_CL_64)
|
||||
@@ -363,6 +378,12 @@ IF(APPLE)
|
||||
ENDIF(OPENAL_FOUND)
|
||||
ENDIF(WITH_OPENAL)
|
||||
|
||||
IF(WITH_JACK)
|
||||
SET(JACK /usr)
|
||||
SET(JACK_INC ${JACK}/include/jack)
|
||||
SET(JACK_LIB jack)
|
||||
SET(JACK_LIBPATH ${JACK}/lib)
|
||||
ENDIF(WITH_JACK)
|
||||
|
||||
SET(PYTHON_VERSION 3.1)
|
||||
|
||||
|
@@ -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}")
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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" {
|
||||
@@ -97,6 +97,11 @@ int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize)
|
||||
case AUD_OPENAL_DEVICE:
|
||||
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;
|
||||
@@ -125,6 +130,9 @@ int* AUD_enumDevices()
|
||||
#endif
|
||||
#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;
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
149
intern/audaspace/jack/AUD_JackDevice.cpp
Normal file
149
intern/audaspace/jack/AUD_JackDevice.cpp
Normal file
@@ -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.
|
||||
}
|
91
intern/audaspace/jack/AUD_JackDevice.h
Normal file
91
intern/audaspace/jack/AUD_JackDevice.h
Normal file
@@ -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
|
@@ -1992,6 +1992,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
|
||||
{0, "AUDIO_DEVICE_NULL", 0, "No Audio", "Null device - there will be no audio output."},
|
||||
{1, "AUDIO_DEVICE_SDL", 0, "SDL", "SDL device - simple direct media layer, recommended for sequencer usage."},
|
||||
{2, "AUDIO_DEVICE_OPENAL", 0, "OpenAL", "OpenAL device - supports 3D audio, recommended for game engine usage."},
|
||||
{3, "AUDIO_DEVICE_JACK", 0, "Jack", "Jack device - open source pro audio, recommended for pro audio users."},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
|
||||
static EnumPropertyItem audio_rate_items[] = {
|
||||
|
Reference in New Issue
Block a user