Страницы

Поиск по вопросам

Показаны сообщения с ярлыком sfml. Показать все сообщения
Показаны сообщения с ярлыком sfml. Показать все сообщения

пятница, 24 января 2020 г.

БПФ звукового сигнала (C++ и SFML)

#cpp #алгоритм #аудио #sfml #fft


У меня вопрос по БПФ звукового сигнала. Я хочу нарисовать график на основе звукового
сигнала. Но я не силен в этой теме. Хочу совета у опытных товарищей с чего начать.

У меня несколько вопросов:
1) Что такое samples (семплы)? Например при использовании мультимедийной библиотеки
SFML для получения семплов используется следующая конструкция:

sf::Buffer Buffer;
Buffer.loadFromFile("sound.wav");
const sf::Int16 *input = Buffer.getSamples();


Так вот я так понимаю семплы это бинарное представление звукового файла? Я правильно
понимаю, что вышепредставленный код, это тоже самое что и:

    typedef short int16;
    int16 *load()
    {
      FILE  *fp;
      if((fp=fopen("sound.wav", "rb"))==NULL) {
        printf("Ошибка при открытии файла.\n");
      }
      fseek(fp, 0, SEEK_END);
      long N = ftell(fp);
      fseek(fp, 0, SEEK_SET);
      int16 *A = new int16[N];
      for(i=0; i


Ответы

Ответ 1



Если речь идет о несжатом звуковом файле, то семпл - это отсчет, полученный при оцифровке сигнала, т.е. просто мгновенное значение амплитуды аналогового сигнала. По этим отсчетам можно построить вашу "синусойду", т.е. представление сигнала во временной области. БПФ же, это быстрое преобразование Фурье, выполнив его мы получаем отображение сигнала в частотной области (разложение сигнала по частотам). Как реализована конкретная библиотека я не знаю, но для алгоритма БПФ необходима кратность 2. Хотя можно и нолики в конце дописать, ну да ладно, это уже ЦОС. Рекомендую вам для начала ознакомится с теоретической стороной вопроса, чтобы четко понимать, что вы делаете. Успехов)

четверг, 9 января 2020 г.

Как избежать пустую нагрузку на процессор в цикле?

#cpp #sfml


Работая над меню игры, которая создаётся с помощью SFML, столкнулся с проблемой "пустой"
загрузки процессора в циклах, которые не высчитывают что-либо в прямом значении этого
слова, а просто ожидают каких-либо событий от пользователя и меняют состояние (выходят
из него или опускаются глубже во внутренние циклы) только тогда, когда что-то происходит,
а до тех пор выводят изображение на экран и тому подобное, тем самым нагружая процессор
на ~20-30%, хотя реально такие мощности не используются. 

Пытался это решить с помощью ожидания события (waitEvent), а не его "вылова" (pollEvent),
но это просто стопорило программу. Может быть как-то неправильно этим пользовался.

Да и не только в данном проекте столкнулся с подобным. В других так же, где были
аналогичные циклы.

Сам "скелет" подобного цикла выглядит примерно так:

while (window.isOpen())
{
    sf::Event event;
    while (window.pollEvent(event))
    {
        if (event.type == sf::Event::Closed)
            window.close();
    }

    window.clear();
    //window.draw(something);
    window.display();
}




Как решать подобные проблемы? Уместно ли будет использовать таймеры или функции типа
Sleep()? Какие технологии можно применять для оптимизации подобных ситуаций? 
    


Ответы

Ответ 1



У класса окна sf::Window имеется метод setFramerateLimit. Но он не гарантирует тот факт что частота кадров будет равна той, которую вы установили. Т.к. он все так же использует функцию sf::sleep. Ограничивает частоту кадров до максимальной фиксированной частоты. Если установлен лимит, окно будет использовать небольшую задержку после каждого вызова display(), чтобы гарантировать что текущий кадр длился достаточно долго, и соответствовать пределу частоты кадров. SFML будет пытаться соответствовать заданному пределу, насколько это возможно, но так как он внутренне использует sf::sleep, точность которого зависит от базовой ОС, результаты могут быть немного неточными (например, вы можете получить 65 кадров в секунду при запросе 60).

Ответ 2



Небольшое вступление. Процессор всегда загружен на 100%, даже если он ничего не делает. Если в диспетчере написано, что процессор загружен на 1%, это лишь значит, что процессор 99% времени работает в холостую, ожидая полезную нагрузку. У разных процессоров есть различные механизмы торможения. Одни процессоры могут полностью уснуть, ожидая прерывания на каком-нибудь порте, другие - предоставляют специализированные команды, которые понижают частоту камня в тех или иных условиях. Если вас интересует, как ограничивают скорость работы главного цикла (например, в играх), то там имеется несколько способов. Каждый со своими клопами. В простых случаях для снижения потока пустой информации через процессор можно использовать Sleep(1); или что-то аналогичное. В сложных стратегиях управления работой процессора можно усыплять процесс/поток с последующим пробуждением по событию + срабатыванию таймера ядра ОС. Важно понимать, что отрисовка и просчеты должны происходить независимо от факта поступления событий, потому что ваше окно может не получать никаких событий несколько секунд, а потом получит 1000 событий за 1 мс. Часто - и обработка событий, и просчеты, и отрисовка - должны происходить независимо. Иногда для каждого процесса используются сложные алгоритмы планирования и предсказания. Это делается для сглаживания поведения игры на различных устройствах.

Ответ 3



Решил данную проблему просто заменой внутреннего цикла обработки событий на условный оператор, который ожидает событие и потом его обрабатывает во вложенных операторах: sf::Event event; if (window.waitEvent(event)) { ... } Получается, что программа на данной строке будет просто ожидать любого события (нажатие клавиши, движение курсора мыши и тд) и дальнейшие итерации основного цикла будут происходить только тогда, когда происходит что-либо, без "пустой" нагрузки на процессор постоянными не контролируемыми итерациями. По сравнению с предыдущим вариантом, нагрузка снизилась до 1-2% без какой-либо потери функциональности.

понедельник, 6 января 2020 г.

Возможно ли подключить библиотеки .NET Framework в .NET Core 2.1.4?

#c_sharp #net #net_core #lib #sfml


Нужно подключить библиотеку в виде DLL, но у меня не получается. Возможно ли это?
    


Ответы

Ответ 1



В общем случае нельзя. Например, потому, что .NET Core является подмножеством .NET Framework. Выход: перевести библиотеку на ту версию .NET Standard, которая поддерживает .NET Core. Многие 3rd party библиотеки потихоньку обзаводятся соответствующии версиями. Upd Говорят еще, что если библиотека не содержит Windows-specific вызовов, то ее можно зареференсить прямо так. Но я не проверял. Какую библиотеку вы пытаетесь подключить и что именно у вас не получается? P.S. Ну и заодно привяжу "обратный" вопрос: Использование Net.Core библиотек в Net.Framewok

пятница, 12 июля 2019 г.

Паразитный курсор в SFML

Дело заключается в том что при вождении курсора в окне sfml при нажатии клавиши движения, персонаж движется быстрее и рывками. Соответственно как координаты курсора не меняются или вообще курсор находится за пределами окна все идет без рывков. При этом в соседнем проекте практический все тоже самое и работает отлично, единственное отличие в коде это динамическое создание окна и обращение к нему через указатель.
void System::CreateWindow(int Width, int Height, string Title) { window.create(VideoMode(Width,Height), Title); window.setVerticalSyncEnabled(true); window.setFramerateLimit(iFrameLimit); }
void System::MainLoop(StateBase& state) { while(window.isOpen()) { Clock(); HandleEvents(event); Update(fTime); Render(window); } } void System::HandleEvents(Event event) { while (window.pollEvent(event)) { if (event.type == event.Closed) window.close(); states.back()->HandleEvents(this); } } void System::Clock() { fTime = clock.getElapsedTime().asMicroseconds(); clock.restart();
fTime /= fGameSpeed;
if (fTime > fGameTick ) fTime = fGameTick;
}
Соседний проект:
void CGameEngine::mainLoop() { while (window->isOpen()) { //TimeWorks float time = (float)clock.getElapsedTime().asMicroseconds(); clock.restart(); time = time / 800;
//Event processor sf::Event event; while (window->pollEvent(event)) { if (event.type == sf::Event::Closed) window->close(); }
CGameEngine::CGameEngine() { gameName = "HellFinger"; playerTileMap = "sprite.png"; mapTileMap = "map.png"; loadConfig(7); window = new sf::RenderWindow(sf::VideoMode(screenResolution.x, screenResolution.y), gameName); camera = new CameraView(0, 0, screenResolution.x, screenResolution.y); player = new Entity(playerTileMap, PLOTM.left, PLOTM.top, PLOTM.width, PLOTM.height); mapImage.loadFromFile("Resources/Images/" + mapTileMap); mapTexture.loadFromImage(mapImage); mapSprite.setTexture(mapTexture); }
P.S. второй код не мой.


Ответ

Решением проблемы являлся вынос update'ов за цикл pollEvent, ибо перемещения курсора в окне добавляет итераций цикла что и повлекло за собой проблему.

понедельник, 11 февраля 2019 г.

Возможно ли подключить библиотеки .NET Framework в .NET Core 2.1.4?

Нужно подключить библиотеку в виде DLL, но у меня не получается. Возможно ли это?


Ответ

В общем случае нельзя. Например, потому, что .NET Core является подмножеством .NET Framework. Выход: перевести библиотеку на ту версию .NET Standard, которая поддерживает .NET Core.
Многие 3rd party библиотеки потихоньку обзаводятся соответствующии версиями.
Upd
Говорят еще, что если библиотека не содержит Windows-specific вызовов, то ее можно зареференсить прямо так. Но я не проверял. Какую библиотеку вы пытаетесь подключить и что именно у вас не получается?
P.S. Ну и заодно привяжу "обратный" вопрос: Использование Net.Core библиотек в Net.Framewok