Skip to content

Instantly share code, notes, and snippets.

@eXpl0it3r
Last active April 27, 2024 17:33
Show Gist options
  • Save eXpl0it3r/8907ff523a2de985d41fcd76665714d8 to your computer and use it in GitHub Desktop.
Save eXpl0it3r/8907ff523a2de985d41fcd76665714d8 to your computer and use it in GitHub Desktop.
VisualSound with SFML
#include <deque>
#include <mutex>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
class MusicVisualizer : public sf::Music, public sf::Drawable
{
public:
void update(const sf::Time& deltaTime);
protected:
[[nodiscard]] bool onGetData(Chunk& data) override;
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
private:
std::recursive_mutex m_mutex;
std::deque<std::uint16_t> m_queue;
std::vector<sf::Vertex> m_vertices;
};
bool MusicVisualizer::onGetData(Chunk& data)
{
auto result = Music::onGetData(data);
{
std::lock_guard lock(m_mutex);
for (auto i = 0u; i < data.sampleCount; ++i)
{
m_queue.emplace_back(data.samples[i]);
}
}
return result;
}
void MusicVisualizer::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
target.draw(m_vertices.data(), m_vertices.size(), sf::PrimitiveType::Points, states);
}
void MusicVisualizer::update(const sf::Time& deltaTime)
{
m_vertices.clear();
{
std::lock_guard lock(m_mutex);
auto size = std::min(static_cast<unsigned int>(m_queue.size()), 1920u);
m_vertices.reserve(size);
for (auto i = 0u; i < size; ++i)
{
auto vertex = sf::Vertex{ {static_cast<float>(i), 0.01f * static_cast<float>(m_queue[i]) + 200.f}, sf::Color::Green};
m_vertices.emplace_back(vertex);
}
}
for (auto i = 0u; !m_queue.empty() && i < static_cast<unsigned int>(deltaTime.asSeconds() * getSampleRate() * getChannelCount()); ++i)
{
m_queue.pop_front();
}
}
int main()
{
auto window = sf::RenderWindow{ sf::VideoMode{ { 1920u, 1080u } }, "CMake SFML Project" };
window.setFramerateLimit(144);
auto visualizer = MusicVisualizer();
if (!visualizer.openFromFile("epic-hollywood-trailer-9489.mp3"))
{
return -1;
}
visualizer.setLoop(true);
visualizer.play();
auto clock = sf::Clock{};
while (window.isOpen())
{
for (auto event = sf::Event{}; window.pollEvent(event);)
{
if (event.type == sf::Event::Closed)
{
window.close();
}
}
auto deltaTime = clock.restart();
visualizer.update(deltaTime);
window.clear();
window.draw(visualizer);
window.display();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment