Мне нужно синхронизировать некоторые ничьи с OpenGL с метроном. Metronome построен с помощью libPD и воспроизводится с RtAudio. Обе вещи работают хорошо (отдельно), но мне нужно переместить объект (треугольник) с импульсом метроном. Приложение также должно воспроизводить клики. Оба действия должны выполняться параллельно (воспроизведение и рисование). Я должен добавить миди-запись. Мое приложение находится на C++. Я попытался запустить это с помощью одного потока, но он не работает. Я попытался следовать этому объяснению: How to make my metronome play at the same time as recording in my program? Gui Library - WxWidgets. Нити сделаны с Poco :: Runnable таким образом:Синхронизация OpenGL с RtAudio (или звуком порта)
class MyThread : public Poco::Runnable {
public:
MyThread(BasicGLPane *pane, std::shared_ptr<SoundManager> man);
virtual void run();
private:
BasicGLPane *_pane;
std::shared_ptr<SoundManager> _man;
};
MyThread::MyThread(BasicGLPane *pane, std::shared_ptr<SoundManager> man) {
_pane = pane;
_man = man;
}
void MyThread::run() {
_man->play();
_pane->startAnimation();
}
BasicGLpane является wxGLCanvas. Пьеса функция класса Sound Manager заключается в следующем:
void SoundManager::play() {
// Init pd
if(!lpd->init(0, 2, sampleRate)) {
std::cerr << "Could not init pd" << std::endl;
exit(1);
}
// Receive messages from pd
lpd->setReceiver(object.get());
lpd->subscribe("metro-bang");
lpd->subscribe("switch");
// send DSP 1 message to pd
lpd->computeAudio(true);
// load the patch
open_patch("metro-main.pd");
std::cout << patch << std::endl;
// Use the RtAudio API to connect to the default audio device.
if(audio->getDeviceCount()==0){
std::cout << "There are no available sound devices." << std::endl;
exit(1);
}
RtAudio::StreamParameters parameters;
parameters.deviceId = audio->getDefaultOutputDevice();
parameters.nChannels = 2;
RtAudio::StreamOptions options;
options.streamName = "Pd Metronome";
options.flags = RTAUDIO_SCHEDULE_REALTIME;
if (audio->getCurrentApi() != RtAudio::MACOSX_CORE) {
options.flags |= RTAUDIO_MINIMIZE_LATENCY; // CoreAudio doesn't seem to like this
}
try {
if(audio->isStreamOpen()) {
audio->closeStream();
}
else {
audio->openStream(¶meters, NULL, RTAUDIO_FLOAT32, sampleRate, &bufferFrames, &audioCallback, lpd.get(), &options);
audio->startStream();
}
}
catch (RtAudioError& e) {
std::cerr << e.getMessage() << std::endl;
exit(1);
}
}
OpenGL рисунок METHODE являются следующие:
void BasicGLPane::startAnimation() {
std::cout<<"Start Animation"<<std::endl;
triangle_1(p1, p2, p3);
Refresh();
}
void BasicGLPane::triangle_1(std::shared_ptr<vertex2f> _p1, std::shared_ptr<vertex2f> _p2, std::shared_ptr<vertex2f> _p3) {
CGLContextObj ctx = CGLGetCurrentContext(); //enable multithreading (only apple)
CGLError err = CGLEnable(ctx, kCGLCEMPEngine);
if (err != kCGLNoError) {
glEnable(GL_MULTISAMPLE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, getWidth(), getHeight(),0 , -1, 1);
glShadeModel(GL_SMOOTH);
glBegin(GL_POLYGON); // Drawing Using Triangles
glColor3f (157.0/255.0, 44.0/255.0, 44.0/255.0);
glVertex3f(p1->x, p1->y, 0.0f); // Top left
glVertex3f(p2->x,p2->y, 0.0f); // Top Right
glVertex3f(p3->x,p3->y, 0.0f); //Bottom
glEnd();
glMatrixMode(GL_MODELVIEW);
glEnable (GL_BLEND);
glLoadIdentity();
glDisable(GL_MULTISAMPLE);
}
}
И нить звонит со следующим несильно:
void BasicGLPane::startThread() {
while (_object->getCounter()<10) { //this is only to test the functionality
thread.start(work);
}
thread.join();
manager->stop();
}
И после этого этот funtion вызывается в Редире:
void BasicGLPane::render(wxPaintEvent& evt) {
//some code here, not important....
startThread();
SwapBuffers();
}
Возможно, я собираюсь изменить этот объект, это не важно сейчас, моя проблема в синхронизации. Я думаю, что RtAudio создает проблемы, потому что я становлюсь EXC_BAD_Acces для getDeviceCount() или любой другой функцией из RtAudio. Это происходит только в контексте потока. Было бы лучше сделать это с помощью Port Audio ?. Было бы неплохо узнать, что я делаю неправильно, или если есть другой способ решить эту проблему.