4
4
mirror of https://github.com/H-uru/korman.git synced 2025-07-14 02:27:36 -04:00

Implement SoundEmit modifier

This sound emitter modifier is almost as fully functional as PlasmaMAX's various sound emitter components. Additional functionality was added to C korlib so that artists can specify OGG Vorbis sound files. If korlib is not compiled, only WAVE sounds can be utilized in Korman. This fixes some of the more fiddly bugs related to exporting to CWE that were seen in PyPRP.

Sound nodes to be implemented...
This commit is contained in:
2016-05-30 21:07:11 -04:00
parent b29f4ebf75
commit 36f0ac194d
10 changed files with 607 additions and 9 deletions

View File

@ -1,6 +1,8 @@
project(korlib)
cmake_minimum_required(VERSION 3.0)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Stolen shamelessly from PyHSPlasma
find_package(PythonLibs REQUIRED)
find_package(PythonInterp "${PYTHONLIBS_VERSION_STRING}" REQUIRED)
@ -10,24 +12,30 @@ if (NOT "${PYTHONLIBS_VERSION_STRING}" STREQUAL "${PYTHON_VERSION_STRING}")
endif()
find_package(HSPlasma REQUIRED)
find_package(Ogg REQUIRED)
find_package(OpenGL REQUIRED)
find_package(Vorbis REQUIRED)
# Da files
set(korlib_HEADERS
buffer.h
korlib.h
sound.h
texture.h
)
set(korlib_SOURCES
buffer.cpp
module.cpp
sound.cpp
texture.cpp
)
include_directories(${HSPlasma_INCLUDE_DIRS})
include_directories(${Ogg_INCLUDE_DIR})
include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${PYTHON_INCLUDE_DIRS})
include_directories(${Vorbis_INCLUDE_DIR})
add_library(_korlib SHARED ${korlib_HEADERS} ${korlib_SOURCES})
if(NOT WIN32)
@ -35,4 +43,4 @@ if(NOT WIN32)
else()
set_target_properties(_korlib PROPERTIES SUFFIX ".pyd")
endif()
target_link_libraries(_korlib HSPlasma ${OPENGL_LIBRARIES} ${PYTHON_LIBRARIES})
target_link_libraries(_korlib HSPlasma ${Ogg_LIBRARIES} ${OPENGL_LIBRARIES} ${PYTHON_LIBRARIES} ${Vorbis_LIBRARIES})

View File

@ -0,0 +1,30 @@
if(Ogg_INCLUDE_DIR AND Ogg_LIBRARY)
set(Ogg_FIND_QUIETLY TRUE)
endif()
find_path(Ogg_INCLUDE_DIR ogg/ogg.h
/usr/local/include
/usr/include
)
find_library(Ogg_LIBRARY NAMES ogg
PATHS /usr/local/lib /usr/lib
)
set(Ogg_LIBRARIES ${Ogg_LIBRARY})
if(Ogg_INCLUDE_DIR AND Ogg_LIBRARY)
set(Ogg_FOUND TRUE)
endif()
if (Ogg_FOUND)
if(NOT Ogg_FIND_QUIETLY)
message(STATUS "Found libogg: ${Ogg_INCLUDE_DIR}")
endif()
else()
if(Ogg_FIND_REQUIRED)
message(FATAL_ERROR "Could not find libogg")
endif()
endif()

View File

@ -0,0 +1,37 @@
if(Vorbis_INCLUDE_DIR AND Vorbis_LIBRARY)
set(Vorbis_FIND_QUIETLY TRUE)
endif()
find_path(Vorbis_INCLUDE_DIR vorbis/codec.h
/usr/local/include
/usr/include
)
find_library(Vorbis_LIBRARY NAMES vorbis
PATHS /usr/local/lib /usr/lib
)
find_library(VorbisFile_LIBRARY NAMES vorbisfile
PATHS /usr/local/lib /usr/lib
)
set(Vorbis_LIBRARIES
${Vorbis_LIBRARY}
${VorbisFile_LIBRARY}
)
if(Vorbis_INCLUDE_DIR AND Vorbis_LIBRARY AND VorbisFile_LIBRARY)
set(Vorbis_FOUND TRUE)
endif()
if (Vorbis_FOUND)
if(NOT Vorbis_FIND_QUIETLY)
message(STATUS "Found libvorbis: ${Vorbis_INCLUDE_DIR}")
endif()
else()
if(Vorbis_FIND_REQUIRED)
message(FATAL_ERROR "Could not find libvorbis")
endif()
endif()

View File

@ -17,6 +17,8 @@
#ifndef _KORLIB_H
#define _KORLIB_H
#define NOMINMAX
#include <cstdint>
#include <Python.h>

View File

@ -15,16 +15,23 @@
*/
#include "buffer.h"
#include "sound.h"
#include "texture.h"
extern "C" {
static PyMethodDef korlib_Methods[] = {
{ _pycs("inspect_vorbisfile"), (PyCFunction)inspect_vorbisfile, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL },
};
static PyModuleDef korlib_Module = {
PyModuleDef_HEAD_INIT, /* m_base */
"_korlib", /* m_name */
"C++ korlib implementation",/* m_doc */
0, /* m_size */
NULL, /* m_methods */
korlib_Methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */

119
korlib/sound.cpp Normal file
View File

@ -0,0 +1,119 @@
/* This file is part of Korman.
*
* Korman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Korman 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Korman. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sound.h"
#include <PRP/Audio/plSoundBuffer.h>
#include <Stream/hsStream.h>
#include <vorbis/vorbisfile.h>
static const int BITS_PER_SAMPLE = 16;
extern "C" {
typedef struct {
PyObject_HEAD
hsStream* fThis;
bool fPyOwned;
} pyStream;
typedef struct {
PyObject_HEAD
plWAVHeader* fThis;
bool fPyOwned;
} pyWAVHeader;
static size_t _read_stream(void* ptr, size_t size, size_t nmemb, void* datasource) {
hsStream* s = static_cast<hsStream*>(datasource);
// hsStream is a bit overzealous protecting us against overreads, so we need to
// make sure to not tick it off.
size_t request = nmemb * size;
size_t remaining = s->size() - s->pos();
size_t min = std::min(request, remaining);
if (min == 0) {
return 0;
} else {
size_t read = s->read(min, ptr);
return read / size;
}
}
static int _seek_stream(void* datasource, ogg_int64_t offset, int whence) {
hsStream* s = static_cast<hsStream*>(datasource);
switch (whence) {
case SEEK_CUR:
s->skip(offset);
break;
case SEEK_SET:
s->seek(offset);
break;
case SEEK_END:
s->seek(s->size() - offset);
break;
}
return 0;
}
static long _tell_stream(void* datasource) {
hsStream* s = static_cast<hsStream*>(datasource);
return s->pos();
}
static ov_callbacks s_callbacks = {
(size_t(*)(void *, size_t, size_t, void *))_read_stream,
(int (*)(void *, ogg_int64_t, int))_seek_stream,
(int (*)(void *))NULL,
(long (*)(void *))_tell_stream,
};
PyObject* inspect_vorbisfile(PyObject*, PyObject* args) {
pyStream* stream;
pyWAVHeader* header;
if (!PyArg_ParseTuple(args, "OO", &stream, &header)) {
PyErr_SetString(PyExc_TypeError, "inspect_vorbisfile expects an hsStream, plWAVHeader");
return NULL;
}
// The OGG file may actually be in Blender's memory, so we will use hsStream. Therefore,
// we must tell vorbisfile how to do this.
OggVorbis_File vorbis;
int result = ov_open_callbacks(stream->fThis, &vorbis, NULL, 0, s_callbacks);
if (result < 0) {
PyErr_Format(PyExc_RuntimeError, "vorbisfile ov_open_callbacks: %d", result);
return NULL;
}
header->fThis->setFormatTag(plWAVHeader::kPCMFormatTag);
header->fThis->setBitsPerSample(BITS_PER_SAMPLE);
vorbis_info* info = ov_info(&vorbis, -1);
header->fThis->setNumChannels(info->channels);
header->fThis->setNumSamplesPerSec(info->rate);
unsigned short align = (BITS_PER_SAMPLE * info->channels) >> 3;
header->fThis->setBlockAlign(align);
header->fThis->setAvgBytesPerSec(info->rate * align);
// This behavior was copied and pasted from CWE
ogg_int64_t size = (ov_pcm_total(&vorbis, -1) - 1) * align;
// Cleanup
ov_clear(&vorbis);
// We got the plWAVHeader from Python because we don't link against PyHSPlasma, only libHSPlasma
// Therefore, we only need to return the size.
return PyLong_FromSsize_t(size);
}
};

28
korlib/sound.h Normal file
View File

@ -0,0 +1,28 @@
/* This file is part of Korman.
*
* Korman is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Korman 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Korman. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _KORLIB_SOUND_H
#define _KORLIB_SOUND_H
#include "korlib.h"
extern "C" {
PyObject* inspect_vorbisfile(PyObject*, PyObject* args);
};
#endif // _KORLIB_SOUND_H