Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - dassie

Pages: [1]
1
Audio / Proper usage of SoundStream class
« on: March 30, 2020, 01:24:00 am »
I am using the SoundStream class to output computed audio and I'm unsure if I'm using it correctly because I notice that the onGetData() function gets called kind of "irregularly".

My implementation is pretty simple. In my class constructor I call initialize(2,44100). From the SFML docs I gathered that the audio format is signed 16 bit integers but there's no mention of how to encode channels, I assumed they need to be output back-to-back (e.g. the stream of Int16s looks like: L0,R0,L1,R1,L2,R2,...). I'm also using version 2.5.1.

onGetData() looks like this:
bool MySoundStream::onGetData(Chunk& chunk)
{
   // buffer is a vector<Int16>

   buffer.clear();
  ReadAudioStream(buffer); // <- This function waits for a lock to access the compute thread's data

   chunk.samples = buffer.data();
   chunk.sampleCount = buffer.size();

   LOG_INFO("Sample count = %d", chunk.sampleCount);

   return chunk.sampleCount > 0;
}


When I notice that onGetData() gets called very rapidly about ~1ms apart, and the second one ends up fetching nothing:

[23:06:58.472] [WARN] MySoundStream::onGetDataSample count = 41300
[23:06:58.472] [WARN] MySoundStream::onGetDataSample count = 0
The thread 0x63ac has exited with code 0 (0x0).
[23:06:58.958] [WARN] MySoundStream::onGetDataSample count = 41300
[23:06:58.958] [WARN] MySoundStream::onGetDataSample count = 0
The thread 0x3eb4 has exited with code 0 (0x0).
[23:06:59.445] [WARN] MySoundStream::onGetDataSample count = 42776
[23:06:59.446] [WARN] MySoundStream::onGetDataSample count = 0
The thread 0x1184 has exited with code 0 (0x0).
[23:06:59.946] [WARN] MySoundStream::onGetDataSample count = 42774
[23:06:59.946] [WARN] MySoundStream::onGetDataSample count = 0
The thread 0x954 has exited with code 0 (0x0).
[23:07:00.445] [WARN] MySoundStream::onGetDataSample count = 41300
[23:07:00.445] [WARN] MySoundStream::onGetDataSample count = 0


Another issue I noticed is _sometimes_ the audio playback stalls a lot. So the logs end up showing large chunks of samples being fetched as it catches up (the problem of reading 0 samples doesn't show up, each consecutive call as it tries to catch up will have data in it). The playback doesn't corrects itself unless I call stop() then play() again.

Sorry for the incomplete code example I'm giving (I can clarify more if needed), I'm moreso asking to confirm that my assumptions about the usage is correct and to find out why onGetData() is being called 1ms apart like that and sometimes not being called for long gaps.

Edit: after checking the source code a bit it looks like this is because the base class is assuming my audio stream is finished when I return false (from looking at SoundStream::fillAndPushBuffer()). I will change up my code to make sure it always returns some data.

2
General / How to lower CPU usage
« on: September 08, 2017, 11:53:42 pm »
So I'm working on a game boy emulator and using SFML to handle the graphics.

My program uses 2 thread: one to run the emulator and another to handle the view port window.

The main thread goes through these steps:
1. Spawn a new thread that handles the viewport window (the window gets a 60fps limit)
2. Waits for user input at the console before starting execution of the game rom by the emulator core
3. Waits for the emulator to finish rendering a frame buffer
4. Sends the frame buffer to the window thread to be display (this step blocks on a mutex thereby meeting the 60fps limit)
5. Repeats from step 3

The window thread is best explained with the code. RunUntilQuitEvent is the entry point for its thread.
void VpWindow::ApplyFrameBuffer()
{
        int size = buffer_width * buffer_height;
        for (int i = 0; i < size; i++)
        {
                int index = i * 4;
                sf_frame_buffer[index + 0] = em_frame_buffer[i].Red * 8;
                sf_frame_buffer[index + 1] = em_frame_buffer[i].Green * 8;
                sf_frame_buffer[index + 2] = em_frame_buffer[i].Blue * 8;
                sf_frame_buffer[index + 3] = 0xFF;
        }

        window->clear();
        texture->update(sf_frame_buffer);
        window->draw(*rectangle, *transform);
        window->display();
}

void VpWindow::RunUntilQuitEvent()
{
        while (window->isOpen())
        {
                Event event;
                while (window->pollEvent(event))
                {
                        if (event.type == Event::Closed)
                        {
                                window->close();
                        }
                        else if (event.type == Event::KeyPressed && HandlesKeyPress)
                        {
                                KeyPressHandler(event);
                        }
                        else if (event.type == Event::KeyReleased && HandlesKeyRelease)
                        {
                                KeyReleaseHandler(event);
                        }
                }

                // Since a window can only be updated from the thread that created it, we can't call ApplyFrameBuffer() from the main thread
                // because the main thread spawns a separate thread for each window before constructing them.
                // The main thread also holds the frame buffer, so to update the window from there it calls the SetFrameBuffer()
                // function which sets the frame_buffer member to a non-null value which signals to this thread that it is ready to be drawn.
                buffer_lock.lock();
                if (em_frame_buffer != nullptr)
                {
                        ApplyFrameBuffer();
                        em_frame_buffer = nullptr;
                }
                buffer_lock.unlock();
        }
}

The problem is I'm getting a pretty high CPU usage (~30%) even before step 3 in the main thread (i.e. before the main thread begins the emulation).

I profiled the program. During the phase before the emulation begins 98% of the CPU time for the window thread is spent on this line: while (window->pollEvent(event))

Once emulation begins, CPU usage drops to around 5%, which is still a little high but more manageable. This time the "while (window->pollEvent(event))" line is using 18% of the window thread's time.

Looking through some other examples, I believe my problem is my window thread should look like this:
while (window->isOpen())
{
    Event event;
    while (window->pollEvent(event)) { ... }

    window->clear(); // optional
    window->draw(...);
    window->display(...);
}
 

Instead it looks more like this:
while (window->isOpen())
{
    Event event;
    while (window->pollEvent(event)) { ... }

    if (<false before emulation begins and true sometimes after it begins)
   {
      window->clear(); // optional
      window->draw(...);
      window->display(...);
   }
}
 

So what is the proper way to share a frame buffer between 2 threads? And what do I do in the window thread before a frame buffer is ready to avoid spinning too much?

Basically, I'm asking what I can do to minimize CPU usage by the window thread.

Any help appreciated :)

3
General / Colour interpolation during scaling
« on: September 02, 2017, 09:13:04 am »
Apologies if this comes off as spamming. I asked my question in this thread, but the title is unrelated so it would be missed.
https://en.sfml-dev.org/forums/index.php?topic=22453.0

The issue I'm having is that I use a scaling transform when drawing a vertex array (of points) to a window. Like so:

   window->clear();
   window->draw(*varr, *transform);
   window->display();

The clear() fills the window with black, then the draw() call "stretches" my vertex array without interpolating the colours in between. So what's supposed to be a white background ends up looking grey (i.e. spaced apart white pixels overtop of a black background).

Screenshot:
http://i.imgur.com/J7z9k1r.png

Is there a way to tell the transform to interpolate the colors in between? In some examples related to sf::Transform, the scaling does interpolate colors. Is it due to the fact that I'm using PrimitiveType::Points and this is why it can't do the interpolation?

4
General / Creating DPI aware programs
« on: September 01, 2017, 02:25:36 am »
So it seems that SFML does not adjust window sizes and such based on the system's DPI settings.

I'm looking for a strategy wherein I can make my SFML program DPI-aware myself (a game boy emulator). I'm able to calculate the scaling factor that is required and now I'm wondering how to account for it.

I could so something as simple as scaling my window size and number of screen pixels per emulator pixel by the same scaling factor. E.g. if the factor is 2, then I'll double the window dimensions, and draw 4 pixels for everyone 1 pixel computed by the emulator.

But I also saw a post where someone suggested using a view and setting the zoom setting on the view object. Is that more efficient? Can the view also scale window dimensions?

Pages: [1]
anything