Skip to content

Commit 53e2fff

Browse files
use looping thread
1 parent eab72a1 commit 53e2fff

File tree

2 files changed

+53
-17
lines changed

2 files changed

+53
-17
lines changed

src/frontend/maxmsp/nn_tilde/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.0)
66
set(C74_MIN_API_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../min-api)
77
include(${C74_MIN_API_DIR}/script/min-pretarget.cmake)
88

9-
9+
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")
1010
#############################################################
1111
# MAX EXTERNAL
1212
#############################################################

src/frontend/maxmsp/nn_tilde/nn_tilde.cpp

+52-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "../../../backend/backend.h"
22
#include "../shared/circular_buffer.h"
33
#include "c74_min.h"
4+
#include <chrono>
5+
#include <semaphore>
46
#include <string>
57
#include <thread>
68
#include <vector>
@@ -50,8 +52,10 @@ class nn : public object<nn>, public vector_operator<> {
5052
std::vector<std::unique_ptr<float[]>> m_in_model, m_out_model;
5153

5254
// AUDIO PERFORM
53-
bool m_use_thread;
55+
bool m_use_thread, m_should_stop_perform_thread;
5456
std::unique_ptr<std::thread> m_compute_thread;
57+
std::binary_semaphore m_data_available_lock, m_result_available_lock;
58+
5559
void operator()(audio_bundle input, audio_bundle output);
5660
void perform(audio_bundle input, audio_bundle output);
5761

@@ -151,14 +155,36 @@ void model_perform(nn *nn_instance) {
151155
in_model.push_back(nn_instance->m_in_model[c].get());
152156
for (int c(0); c < nn_instance->m_out_dim; c++)
153157
out_model.push_back(nn_instance->m_out_model[c].get());
158+
154159
nn_instance->m_model->perform(in_model, out_model, nn_instance->m_buffer_size,
155160
nn_instance->m_method, 1);
156161
}
157162

163+
void model_perform_loop(nn *nn_instance) {
164+
std::vector<float *> in_model, out_model;
165+
166+
for (auto &ptr : nn_instance->m_in_model)
167+
in_model.push_back(ptr.get());
168+
169+
for (auto &ptr : nn_instance->m_out_model)
170+
out_model.push_back(ptr.get());
171+
172+
while (!nn_instance->m_should_stop_perform_thread) {
173+
if (nn_instance->m_data_available_lock.try_acquire_for(
174+
std::chrono::milliseconds(200))) {
175+
nn_instance->m_model->perform(in_model, out_model,
176+
nn_instance->m_buffer_size,
177+
nn_instance->m_method, 1);
178+
nn_instance->m_result_available_lock.release();
179+
}
180+
}
181+
}
182+
158183
nn::nn(const atoms &args)
159184
: m_compute_thread(nullptr), m_in_dim(1), m_in_ratio(1), m_out_dim(1),
160185
m_out_ratio(1), m_buffer_size(4096), m_method("forward"),
161-
m_use_thread(true) {
186+
m_use_thread(true), m_data_available_lock(0), m_result_available_lock(1),
187+
m_should_stop_perform_thread(false) {
162188

163189
m_model = std::make_unique<Backend>();
164190
m_is_backend_init = true;
@@ -261,9 +287,13 @@ nn::nn(const atoms &args)
261287
m_out_buffer[i].initialize(m_buffer_size);
262288
m_out_model.push_back(std::make_unique<float[]>(m_buffer_size));
263289
}
290+
291+
if (m_use_thread)
292+
m_compute_thread = std::make_unique<std::thread>(model_perform_loop, this);
264293
}
265294

266295
nn::~nn() {
296+
m_should_stop_perform_thread = true;
267297
if (m_compute_thread)
268298
m_compute_thread->join();
269299
}
@@ -318,24 +348,30 @@ void nn::perform(audio_bundle input, audio_bundle output) {
318348
}
319349

320350
if (m_in_buffer[0].full()) { // BUFFER IS FULL
321-
// IF USE THREAD, CHECK THAT COMPUTATION IS OVER
322-
if (m_compute_thread && m_use_thread) {
323-
m_compute_thread->join();
324-
}
351+
if (!m_use_thread) {
352+
// TRANSFER MEMORY BETWEEN INPUT CIRCULAR BUFFER AND MODEL BUFFER
353+
for (int c(0); c < m_in_dim; c++)
354+
m_in_buffer[c].get(m_in_model[c].get(), m_buffer_size);
325355

326-
// TRANSFER MEMORY BETWEEN INPUT CIRCULAR BUFFER AND MODEL BUFFER
327-
for (int c(0); c < m_in_dim; c++)
328-
m_in_buffer[c].get(m_in_model[c].get(), m_buffer_size);
329-
330-
if (!m_use_thread) // PROCESS DATA RIGHT NOW
356+
// CALL MODEL PERFORM IN CURRENT THREAD
331357
model_perform(this);
332358

333-
// TRANSFER MEMORY BETWEEN OUTPUT CIRCULAR BUFFER AND MODEL BUFFER
334-
for (int c(0); c < m_out_dim; c++)
335-
m_out_buffer[c].put(m_out_model[c].get(), m_buffer_size);
359+
// TRANSFER MEMORY BETWEEN OUTPUT CIRCULAR BUFFER AND MODEL BUFFER
360+
for (int c(0); c < m_out_dim; c++)
361+
m_out_buffer[c].put(m_out_model[c].get(), m_buffer_size);
362+
363+
} else if (m_result_available_lock.try_acquire()) {
364+
// TRANSFER MEMORY BETWEEN INPUT CIRCULAR BUFFER AND MODEL BUFFER
365+
for (int c(0); c < m_in_dim; c++)
366+
m_in_buffer[c].get(m_in_model[c].get(), m_buffer_size);
336367

337-
if (m_use_thread) // PROCESS DATA LATER
338-
m_compute_thread = std::make_unique<std::thread>(model_perform, this);
368+
// TRANSFER MEMORY BETWEEN OUTPUT CIRCULAR BUFFER AND MODEL BUFFER
369+
for (int c(0); c < m_out_dim; c++)
370+
m_out_buffer[c].put(m_out_model[c].get(), m_buffer_size);
371+
372+
// SIGNAL PERFORM THREAD THAT DATA IS AVAILABLE
373+
m_data_available_lock.release();
374+
}
339375
}
340376

341377
// COPY CIRCULAR BUFFER TO OUTPUT

0 commit comments

Comments
 (0)