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

Author Topic: getPlayingOffset returns 0 when it shouldn't  (Read 5938 times)

0 Members and 1 Guest are viewing this topic.

Eilessa

  • Newbie
  • *
  • Posts: 9
    • View Profile
getPlayingOffset returns 0 when it shouldn't
« on: August 08, 2014, 08:50:38 am »
Hi,

I must be missing something, because it doesn't work. First of all, a bit of background of what I'm trying to do: I have an assignment in school for which I need to modify audio. The bit I'm stuck on is changing volume. Because of the assignment - I'm not allowed to use the built in volume function.

What I'm trying to do: I have the original buffer, as well as a "current buffer". This is because I want to keep the original file for easy recovery after making changes (more are to come). I copy the contents of the original buffer into an sf::Int16 array that I modify, load into the current buffer and then I call my sound variable's setBuffer-method passing in the current buffer. So far so good, the sound still works.

But, this causes the sound to restart from the beginning (naturally) which I don't want. To solve that, before I change the buffer, I save the playing offset to a variable and after the buffer has been changed, I set the playing offset to that time. As this did not work, I printed the values I got from getPlayingOffset and it turns out, other than the first time, this returns 0. Why is this?

The code segment for the above:
   
int sampleCount = m_origBuffer.getSampleCount();
        const sf::Int16* origSamples = m_origBuffer.getSamples();
        sf::Int16* samples = new sf::Int16[sampleCount];

        for (int i = 0; i < sampleCount; ++i)
        {
                samples[i] = origSamples[i] * m_volume;
        }

        m_currBuffer.loadFromSamples(samples, sampleCount, m_origBuffer.getChannelCount(), m_origBuffer.getSampleRate());
        sf::Time time = m_sound.getPlayingOffset();
        std::cout << "Sound offset at change: " << time.asMilliseconds() << "\t";
        m_sound.setBuffer(m_currBuffer);
        m_sound.play();
        m_sound.setPlayingOffset(time);

        std::cout << "Offset set to time: " << time.asMilliseconds() << std::endl;

Thankful for help!
« Last Edit: August 08, 2014, 09:55:44 am by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #1 on: August 08, 2014, 09:13:20 am »
You must call setPlayingOffset after play ;)

By the way, you have a memory leak (unless you delete the temporary buffer later). Use standard containers instead, like std::vector.
Laurent Gomila - SFML developer

Eilessa

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #2 on: August 08, 2014, 09:26:08 am »
Thank you for your reply! Unfortunately, I have tried that too - this is just left from when I tried another order to see if that was the error. Then I forgot to change it back before posting. I'll update it!

Thanks for the hint about memory leaks :)

Edit: Right, the problem I think is that time is always 0 apart from the very first time this is performed. I think that's the problem. That's why I think I have made a mistake with getPlayingOffset
« Last Edit: August 08, 2014, 09:28:02 am by Eilessa »

Eilessa

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #3 on: August 08, 2014, 09:36:55 am »
Here is the full code of that part (edited out my debug printing when posting before)

   
m_currBuffer.loadFromSamples(samples, sampleCount, m_origBuffer.getChannelCount(), m_origBuffer.getSampleRate());
        m_sound.pause();
        sf::Time time = m_sound.getPlayingOffset();
        std::cout << "Sound offset at change: " << time.asMilliseconds() << "\t";
        m_sound.setBuffer(m_currBuffer);
        m_sound.play();
        m_sound.setPlayingOffset(time);

        std::cout << "Offset set to time: " << time.asMilliseconds() << std::endl;

As said previously, I find that time is always 0. That seems erroneous to me, but it's probably that I have misunderstood something about how to use the functions. I just can't figure out what!
« Last Edit: August 08, 2014, 09:55:56 am by Laurent »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #4 on: August 08, 2014, 09:59:22 am »
You should try to write a complete and minimal example that reproduces the problem. Once it's done, simplify it further (don't change the sound buffer, etc.) to see which part of the code causes the problem. Then if you still can't figure out what's wrong, you can post this complete and minimal code on the forum.
Laurent Gomila - SFML developer

Eilessa

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #5 on: August 08, 2014, 10:31:02 am »
I hope the following program fully satisfies your request. If not, let me know what I need to fix and I'll update! This is as minimal as I can make it, all in the main.cpp-file:

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>

sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
bool wasKeyPressed = false; // Used so that it only detects the first keypress and not continuously.
sf::SoundBuffer m_origBuffer;
sf::SoundBuffer m_currBuffer;
sf::Sound m_sound;

void changeBuffer()
{
        int sampleCount = m_origBuffer.getSampleCount();
        const sf::Int16* origSamples = m_origBuffer.getSamples();

        m_currBuffer.loadFromSamples(origSamples, sampleCount, m_origBuffer.getChannelCount(), m_origBuffer.getSampleRate());
        sf::Time time = m_sound.getPlayingOffset();
        std::cout << "Sound offset at change: " << time.asMilliseconds() << "\t";
        m_sound.setBuffer(m_currBuffer);
        m_sound.play();
        m_sound.setPlayingOffset(time);

        std::cout << "Offset set to time: " << time.asMilliseconds() << std::endl;
}

int main()
{
        if (!m_origBuffer.loadFromFile("../Assets/Ape.wav"))
                std::cout << "ERROR: Failed to load file!" << std::endl;
        m_sound.setBuffer(m_origBuffer);
        m_sound.setLoop(true);
        m_sound.play();

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

                window.clear();

                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Num1))
                {
                        if (!wasKeyPressed)
                                changeBuffer();
                        wasKeyPressed = true;
                }
                else
                        wasKeyPressed = false;

                window.display();
        }

        return 0;
}

Pressing the 1 key makes the sound restart from the beginning of the clip. The debug printing of the time value shows that the first time, there is a value other than 0, but all the other times, the time is 0. This is peculiar as I would have expected some other value from getPlayingOffset().

I have tried two modifications to the code above:
  • Commenting out the row m_sound.setBuffer(m_currBuffer); this worked, no lag and time != 0
  • Changing that same row to m_sound.setBuffer(m_origBuffer); which also worked, no lag and time was != 0.

It is peculiar though, as this example merely copies the m_origBuffer by sending the samples unchanged into the m_currBuffer load function as well as copy all other information from m_origBuffer. I can't make out what to do of it as I can't think of any ways of completing my assignment without changing buffers.

Thank you so much for the time you take to help me!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #6 on: August 08, 2014, 10:36:13 am »
Thanks for the minimal code :)

I can't spot any obvious error in it, I'll try to test it if I can find the time.
Laurent Gomila - SFML developer

Eilessa

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #7 on: August 08, 2014, 04:00:10 pm »
Thank you so much! Hope you have better luck than I've had :-\

maly

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #8 on: August 08, 2014, 07:58:10 pm »
        sf::Time time = m_sound.getPlayingOffset();
        m_currBuffer.loadFromSamples(origSamples, sampleCount, m_origBuffer.getChannelCount(), m_origBuffer.getSampleRate());
        //sf::Time time = m_sound.getPlayingOffset();

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
AW: getPlayingOffset returns 0 when it shouldn't
« Reply #9 on: August 10, 2014, 10:21:59 pm »
Ard you using the latest master from GitHib, because binary1248 has recently fixed a few things with the sound stream.

maly whate are you trying to communicate with your code?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

maly

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #10 on: August 11, 2014, 11:04:40 am »
Quote
maly whate are you trying to communicate with your code?
my code refers to the example and says "move up this line".

btw, latest source does not fix that problem.

ps. i hate english grammar.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #11 on: August 11, 2014, 11:10:20 am »
Switching these two lines is not the solution (it may work but it's not clean), but it raises an interesting point: the second time changeBuffer() is called, m_currBuffer is already assigned to m_sound. Therefore, calling m_currBuffer.loadFromSamples in this context most likely resets m_sound.

You should load new data in a sf::SoundBuffer different from m_sound's current buffer. It should solve your problem.
Laurent Gomila - SFML developer

maly

  • Newbie
  • *
  • Posts: 14
    • View Profile
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #12 on: August 12, 2014, 07:04:02 am »
Quote
Switching these two lines is not the solution (it may work but it's not clean)
This way is a bit hacky but it can save memory.

Quote
You should load new data in a sf::SoundBuffer different from m_sound's current buffer.
Without any information about this limitation it is also not clear.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: getPlayingOffset returns 0 when it shouldn't
« Reply #13 on: August 12, 2014, 07:48:08 am »
Quote
This way is a bit hacky but it can save memory.
?

Quote
Without any information about this limitation it is also not clear.
It's not a limitation, just an obvious fact. If you reset the playing sound's buffer then it will be stopped and reset. It won't smoothly transition to the new content of the buffer at the current playing position :P
Laurent Gomila - SFML developer