Рисование аудио формы волны в winforms с использованием OpenAL и VC ++ - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть проект по изучению обработки сигналов, и я обязан записывать звук из какого-либо источника (например, микрофона) и отображать форму сигнала и его БПФ на двух графиках. Я не могу предоставить функции отображения буфера на графике и не останавливать всю программу.

Поскольку я еще не знаю C #, я выбрал Winforms в C ++ / CLI и OpenAL для захвата звука (0 опыта в обработке звука, и это было рекомендовано в нескольких потоках, и остальная часть моей команды работает с ним, поэтому я ' м обязана его использовать). У меня уже есть код для выбора звукового устройства и записи звука в буфер. Я знаю, что цикл while ниже останавливает программу. Я думал об использовании многопоточности, но не знал, как его использовать. Или события ...

Это код для начала захвата, внутри некоторого события кнопки.

int go = 0;

const int SRATE = 44100;
const int SSIZE = 1024;
ALCdevice *hydromike;

ALbyte buffer[22050];
ALint sample;

some_event {
const char* diwajs = (msclr::interop::marshal_as<std::string>(item)).c_str();
        hydromike = alcCaptureOpenDevice(diwajs, SRATE, AL_FORMAT_MONO16, SSIZE);
        alcCaptureStart(hydromike);

        buffering(); //function call for starting the buffer
}

void buffering(void)
{
while (go) {

    alcGetIntegerv(hydromike, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
    alcCaptureSamples(hydromike, (ALCvoid *)buffer, sample);

}
}

void drw(void)
{
chart1->Series["Bufor"]->Points->Clear();
for (int i = 0; i < 22050; i++)
{
    chart1->Series["Bufor"]->Points->AddXY(i, (int)buffer[i]);
}
}

Я бы хотел, чтобы это работало так: https://www.youtube.com/watch?v=q9cRZuosrOs

1 Ответ

0 голосов
/ 09 мая 2019

Мне удалось завершить код, проблема была в том, что потоки пользовательского интерфейса и OpenAL мешали друг другу, что привело к зависанию приложения. Запуск буферизации в другом потоке и установка семафора решили проблему.

static Semaphore^ drawingSem = gcnew Semaphore(1, 1);
    Thread^ oThread;
alcCaptureStart(hydromike);

            oThread = gcnew Thread(gcnew ThreadStart(buffering));
            oThread->Start();

static void buffering()
{
while (go) {
    drawingSem->WaitOne();
    alcGetIntegerv(hydromike, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), buffer);

    alcCaptureSamples(hydromike, (ALCvoid *)buffer, sample*2);

    drawingSem->Release();


}
}

void MyForm::drw()
{

drawingSem->WaitOne();

chart1->Series["Bufor"]->Points->Clear();

for (int i = 0; i < bufsize; i++)
{
    chart1->Series["Bufor"]->Points->AddXY(i, (int)buffer[i]);
}
drawingSem->Release();
}

private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) {

drw();

}
...