Skip to content

Commit

Permalink
Add shared memory
Browse files Browse the repository at this point in the history
  • Loading branch information
ShirasawaSama committed Feb 20, 2023
1 parent 9c49910 commit b7498f1
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 22 deletions.
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "JUCE"]
path = JUCE
url = https://github.com/juce-framework/JUCE.git
[submodule "cpp-ipc"]
path = cpp-ipc
url = https://github.com/mutouyun/cpp-ipc.git
[submodule "JavaSharedMemory"]
path = JavaSharedMemory
url = https://github.com/ShirasawaSama/JavaSharedMemory.git
19 changes: 11 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ add_definitions(-DJUCE_USE_MP3AUDIOFORMAT -DJUCE_PLUGINHOST_VST3 -DJUCE_PLUGINHO

file(GLOB EIM_SRC_FILES "src/*.cpp" "src/*.h")

add_subdirectory(JavaSharedMemory)

add_subdirectory(JUCE)
juce_add_console_app(EIMHost
juce_add_console_app(${PROJECT_NAME}
VERSION "1.0.0"
PRODUCT_NAME "EIMHost"
PRODUCT_NAME ${PROJECT_NAME}
COMPANY_NAME "Echo In Mirror"
ICON_SMALL "resources/logo128.png"
ICON_BIG "resources/logo512.png"
)
_juce_configure_bundle(EIMHost EIMHost)
_juce_add_resources_rc(EIMHost EIMHost)
target_sources(EIMHost PRIVATE ${EIM_SRC_FILES})
_juce_configure_bundle(${PROJECT_NAME} ${PROJECT_NAME})
_juce_add_resources_rc(${PROJECT_NAME} ${PROJECT_NAME})
target_sources(${PROJECT_NAME} PRIVATE ${EIM_SRC_FILES})

if(MSVC)
set(thirdpartyPath ${CMAKE_CURRENT_BINARY_DIR}/thirdparty)
Expand Down Expand Up @@ -49,20 +51,21 @@ if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHa")
set_property(TARGET EIMHost PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set_property(TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif(MSVC)

target_compile_definitions(EIMHost
target_compile_definitions(${PROJECT_NAME}
PRIVATE
JUCE_WEB_BROWSER=0
JUCE_USE_CURL=0
JUCE_APPLICATION_NAME_STRING="$<TARGET_PROPERTY:EIMHost,JUCE_PRODUCT_NAME>"
JUCE_APPLICATION_VERSION_STRING="$<TARGET_PROPERTY:EIMHost,JUCE_VERSION>")

target_link_libraries(EIMHost
target_link_libraries(${PROJECT_NAME}
PRIVATE
juce::juce_gui_extra
juce::juce_audio_utils
java_shared_memory
PUBLIC
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags
Expand Down
1 change: 1 addition & 0 deletions JavaSharedMemory
Submodule JavaSharedMemory added at b55aa3
67 changes: 56 additions & 11 deletions src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma warning(disable: 6029)

#include "PluginWindow.h"
#include <jshm.h>
#include <io.h>
#include <fcntl.h>
#include <juce_audio_devices/juce_audio_devices.h>
Expand Down Expand Up @@ -44,6 +45,9 @@ std::string readString() {
class EIMPluginHost : public juce::JUCEApplication, public juce::AudioPlayHead, public juce::AudioProcessorListener, private juce::Thread {
public:
EIMPluginHost(): juce::AudioPlayHead(), juce::Thread("IO Thread") { }
~EIMPluginHost() {
shm.reset();
}

const juce::String getApplicationName() override { return "EIMPluginHost"; }
const juce::String getApplicationVersion() override { return "0.0.0"; }
Expand Down Expand Up @@ -92,11 +96,33 @@ class EIMPluginHost : public juce::JUCEApplication, public juce::AudioPlayHead,
while (!threadShouldExit() && std::fread(&id, 1, 1, stdin) == 1) {
switch (id) {
case 0: {
char enabledSharedMemory;
READ(sampleRate);
READ(bufferSize);
READ(enabledSharedMemory);
juce::MessageManagerLock mml(Thread::getCurrentThread());
if (!mml.lockWasGained()) return;
buffer.setSize(juce::jmax(processor->getTotalNumInputChannels(), processor->getTotalNumOutputChannels()), bufferSize);
auto channels = juce::jmax(processor->getTotalNumInputChannels(), processor->getTotalNumOutputChannels());
bool setInnerBuffer = true;
if (enabledSharedMemory) {
int shmSize;
READ(shmSize);
if (!shm || shmSize) {
shm.reset();
auto shmName = args->getValueForOption("-M|--memory");
if (shmName.isNotEmpty()) {
shm.reset(jshm::shared_memory::open(shmName.toRawUTF8(), shmSize));
if (shm) {
auto buffers = new float* [channels];
for (int i = 0; i < channels; i++) buffers[i] = reinterpret_cast<float*>(shm->address()) + i * bufferSize;
buffer = juce::AudioBuffer<float>(buffers, channels, bufferSize);
delete[] buffers;
setInnerBuffer = false;
}
}
} else setInnerBuffer = false;
}
if (setInnerBuffer) buffer = juce::AudioBuffer<float>(channels, bufferSize);
processor->prepareToPlay(sampleRate, bufferSize);
break;
}
Expand Down Expand Up @@ -209,6 +235,7 @@ class EIMPluginHost : public juce::JUCEApplication, public juce::AudioPlayHead,
private:
juce::MidiBuffer midiBuffer;
juce::AudioBuffer<float> buffer;
std::unique_ptr<jshm::shared_memory> shm;
std::unique_ptr<PluginWindow> window;
std::unique_ptr<juce::AudioPluginInstance> processor;
juce::AudioPlayHead::PositionInfo positionInfo;
Expand Down Expand Up @@ -258,7 +285,15 @@ class EIMPluginHost : public juce::JUCEApplication, public juce::AudioPlayHead,

class AudioCallback : public juce::AudioIODeviceCallback {
public:
AudioCallback(juce::AudioDeviceManager& deviceManager): deviceManager(deviceManager) {}
AudioCallback(juce::AudioDeviceManager& deviceManager, juce::String shmName, int memorySize): deviceManager(deviceManager) {
if (shmName.isNotEmpty()) {
shm.reset(jshm::shared_memory::open(shmName.toRawUTF8(), memorySize));
if (!shm) exit();
}
}
~AudioCallback() {
shm.reset();
}

void audioDeviceIOCallbackWithContext(const float* const*, int, float* const* outputChannelData, int, int, const juce::AudioIODeviceCallbackContext&) override {
writeCerr((char)0);
Expand All @@ -272,7 +307,11 @@ class AudioCallback : public juce::AudioIODeviceCallback {
case 0: {
char numOutputChannels;
READ(numOutputChannels);
for (int i = 0; i < numOutputChannels; i++) std::fread(outputChannelData[i], sizeof(float), setup.bufferSize, stdin);
if (shm) {
auto inData = reinterpret_cast<float*>(shm->address());
for (int i = 0; i < numOutputChannels; i++)
std::memcpy(outputChannelData[i], inData + i * setup.bufferSize, setup.bufferSize * sizeof(float));
} else for (int i = 0; i < numOutputChannels; i++) std::fread(outputChannelData[i], sizeof(float), setup.bufferSize, stdin);
break;
}
case 1:
Expand All @@ -299,20 +338,25 @@ class AudioCallback : public juce::AudioIODeviceCallback {
}

void audioDeviceAboutToStart(juce::AudioIODevice* device) override {
auto bufSize = device->getCurrentBufferSizeSamples();
auto bufferSizes = device->getAvailableBufferSizes();
auto sampleRates = device->getAvailableSampleRates();
writeCerr((char)1);
writeString("[" + device->getTypeName() + "] " + device->getName(), stderr);
writeCerr(device->getInputLatencyInSamples());
writeCerr(device->getOutputLatencyInSamples());
writeCerr((int)device->getCurrentSampleRate());
writeCerr(device->getCurrentBufferSizeSamples());
auto sampleRates = device->getAvailableSampleRates();
writeCerr(bufSize);
writeCerr(sampleRates.size());
for (auto it : sampleRates) writeCerr((int)it);
auto bufferSizes = device->getAvailableBufferSizes();
writeCerr(bufferSizes.size());
for (int it : bufferSizes) writeCerr(it);
writeCerr((char)device->hasControlPanel());
fflush(stderr);
int outBufferSize;
READ(outBufferSize);
if (setup.bufferSize != bufSize) setup.bufferSize = bufSize;
if (shm && outBufferSize) shm.reset(jshm::shared_memory::open(shm->name(), outBufferSize));
}

void audioDeviceStopped() override {
Expand Down Expand Up @@ -351,6 +395,7 @@ class AudioCallback : public juce::AudioIODeviceCallback {
}

private:
std::unique_ptr<jshm::shared_memory> shm;
bool isErrorExit = false, isRestarting = false;
juce::AudioDeviceManager& deviceManager;
};
Expand Down Expand Up @@ -446,8 +491,10 @@ int main(int argc, char* argv[]) {
fflush(stderr);

if (deviceName == "#") deviceName = readString();

AudioCallback audioCallback(deviceManager);

auto memorySize = args->getValueForOption("-MS|--memory-size");
AudioCallback audioCallback(deviceManager, args->getValueForOption("-M|--memory"),
memorySize.isEmpty() ? 0 : memorySize.getIntValue());
for (auto& it : deviceManager.getAvailableDeviceTypes()) {
if (deviceType == it->getTypeName()) it->scanForDevices();
}
Expand Down Expand Up @@ -477,9 +524,7 @@ int main(int argc, char* argv[]) {
if (file.exists()) {
juce::File vmoptions("./.vmoptions");
juce::StringArray arr;
if (vmoptions.exists()) {
vmoptions.readLines(arr);
}
if (vmoptions.exists()) vmoptions.readLines(arr);
arr.insert(0, file.getFullPathName());
arr.add("-jar");
arr.add("EchoInMirror.jar");
Expand Down

0 comments on commit b7498f1

Please sign in to comment.