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

Author Topic: Enhanced Music Control  (Read 18843 times)

0 Members and 1 Guest are viewing this topic.

Ryan Bram

  • Newbie
  • *
  • Posts: 6
    • View Profile
Enhanced Music Control
« on: February 20, 2012, 10:02:43 am »
Greetings,

My name is Ryan and I have some request for SFML Developer:

1. Can you add new function for SFML to play Standard MIDI Files format (.mid) and some module music format (.mod, .it, .xm, etc). For Standard MIDI Files, you may use Fluidsynth library with soundfont (.sf2) http://sourceforge.net/apps/trac/fluidsynth/, and for module music format you can use OpenMPT library http://openmpt.org/.

2. Can you add function to make SFML looping the music for certain point by reading something like additional meta tag in music file. In RPG Maker VX, we can add LOOPSTART and LOOPLENGTH then RPG Maker VX will automatically play the music over and over with predefined loop point in meta tag as the reference.

Thanks,
Ryan Bram

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Enhanced Music Control
« Reply #1 on: February 20, 2012, 10:12:49 am »
Hi

Both features have already been discussed, have you searched the forum and the issue tracker first?
Laurent Gomila - SFML developer

Ryan Bram

  • Newbie
  • *
  • Posts: 6
    • View Profile
Enhanced Music Control
« Reply #2 on: February 21, 2012, 12:57:25 am »
I already search related post and I found it. This http://www.sfml-dev.org/forum/viewtopic.php?t=577&sid=778e7d9f8321dab69d65fa6ab4abd3c5 and http://www.sfml-dev.org/forum/viewtopic.php?t=1659 and http://www.sfml-dev.org/forum/viewtopic.php?p=19539
I'm really sorry but I think I didn't see any progress in SFML development since the last post, so I just want to provide vote for the requests and to refresh the topics.

Thanks for kindly answering my question and hearing your user opinion.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Enhanced Music Control
« Reply #3 on: February 21, 2012, 08:16:48 am »
It's not a problem of progress.

Like I say in those threads, MIDI is unlikely to be supported because:
- it's hard to find a library that converts MIDI files to audio samples (most libraries directly play songs)
- MIDI requires an instrument bank, which is usually too big to be embedded in SFML, and not standard enough not to be embedded in SFML

Looping points are an important feature but I have to find a nice way to integrate them to the public API. Using specific metadata is not an option, since SFML supports many standard audio formats.
Laurent Gomila - SFML developer

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Enhanced Music Control
« Reply #4 on: February 21, 2012, 01:13:16 pm »
Quote from: Laurent
Looping points are an important feature but I have to find a nice way to integrate them to the public API. Using specific metadata is not an option, since SFML supports many standard audio formats.

I've implemented the looping point feature myself in an "old" version of SFML 2.0. I think, I only did minor edits in SoundStream.
You're only able to set the loop start point, where to go when the stream ends and looping is enabled.


// SoundStream.hpp //
class SFML_API SoundStream : SoundSource
{
public:
    ...
    ////////////////////////////////////////////////////////////
    /// \brief Set whether or not the stream should loop after reaching the end
    ///
    /// If set, the stream will restart from beginning after
    /// reaching the end and so on, until it is stopped or
    /// SetLoop(false) is called.
    /// The default looping state for streams is false.
    ///
    /// \param loop  True to play in loop, false to play once
    /// \param start Offset of loop start, in milliseconds
    ///
    /// \see GetLoop
    ///
    ////////////////////////////////////////////////////////////
    void SetLoop(bool loop, Uint32 start=0);
    ...
private:
    ...
    bool          myLoop;                     ///< Loop flag (true to loop, false to play once)
    Uint32        myLoopStart;                ///< Start point of loop in milliseconds
    ...
};
 

// SoundSource.cpp //
SoundStream::SoundStream() :
myThread          (&SoundStream::Stream, this),
myIsStreaming     (false),
myChannelsCount   (0),
mySampleRate      (0),
myFormat          (0),
myLoop            (false),
myLoopStart       (0),
mySamplesProcessed(0)
{

}

...

void SoundStream::SetLoop(bool loop, Uint32 start)
{
    myLoop = loop;
    myLoopStart = start;
}

...

bool SoundStream::FillAndPushBuffer(unsigned int bufferNum)
{
    bool requestStop = false;

    // Acquire audio data
    Chunk data = {NULL, 0};
    if (!OnGetData(data))
    {
        // Mark the buffer as the last one (so that we know when to reset the playing position)
        myEndBuffers[bufferNum] = true;

        // Check if the stream must loop or stop
        if (myLoop)
        {
            // Return to the beginning of the stream source
            OnSeek(myLoopStart);

            // If we previously had no data, try to fill the buffer once again
            if (!data.Samples || (data.NbSamples == 0))
            {
                return FillAndPushBuffer(bufferNum);
            }
        }
        else
        {
            // Not looping: request stop
            requestStop = true;
        }
    }

    // Fill the buffer if some data was returned
    if (data.Samples && data.NbSamples)
    {
        unsigned int buffer = myBuffers[bufferNum];

        // Fill the buffer
        ALsizei size = static_cast<ALsizei>(data.NbSamples) * sizeof(Int16);
        ALCheck(alBufferData(buffer, myFormat, data.Samples, size, mySampleRate));

        // Push it into the sound queue
        ALCheck(alSourceQueueBuffers(mySource, 1, &buffer));
    }

    return requestStop;
}
 


Hope it might help.
« Last Edit: March 26, 2012, 08:10:11 pm by Shy Guy »
Please note that my previous display name was "Shy Guy".

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Enhanced Music Control
« Reply #5 on: February 21, 2012, 01:23:10 pm »
Yeah, implementation is easy. In fact I'm more concerned about the design.

Your solution is more like a quick workaround.
Laurent Gomila - SFML developer

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Enhanced Music Control
« Reply #6 on: February 21, 2012, 01:35:30 pm »
Quote from: "Laurent"
Yeah, implementation is easy. In fact I'm more concerned about the design.

Your solution is more like a quick workaround.

Well, I think, users should set the loop points via a function themselves, so I would do a function for the music "SetLoopPoints" or only "SetLoopStart".

Or what exactly do you mean by design?
Please note that my previous display name was "Shy Guy".

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Enhanced Music Control
« Reply #7 on: February 21, 2012, 01:52:11 pm »
I mean:
  • try to enable this feature in sf::Sound too
  • think about how many loop points we want/can have
  • should they be specified with a timestamp or a sample index?
  • if we have a "start" loop point, is it active right from the start, or only after the first loop?
  • how to remove loop points? (using 0 or music.GetDuration() would not be reliable)
  • should we add a way to enable/disable loop points without removing them?
  • should we investigate metadata to see if we can enable loop points there for some audio formats, in addition to the C++ API?
  • ... probably many other questions because I've only thought about it for 5 minutes, and I'm not a typical user of this feature
So, I mean thinking about a global, smart and efficient solution, that takes all the possible issues in account.
Laurent Gomila - SFML developer

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Enhanced Music Control
« Reply #8 on: February 21, 2012, 02:07:57 pm »
Quote from: "Laurent"
I mean:
  • try to enable this feature in sf::Sound too
  • think about how many loop points we want/can have
  • should they be specified with a timestamp or a sample index?
  • if we have a "start" loop point, is it active right from the start, or only after the first loop?
  • how to remove loop points? (using 0 or music.GetDuration() would not be reliable)
  • should we add a way to enable/disable loop points without removing them?
  • should we investigate metadata to see if we can enable loop points there for some audio formats, in addition to the C++ API?
  • ... probably many other questions because I've only thought about it for 5 minutes, and I'm not a typical user of this feature
So, I mean thinking about a global, smart and efficient solution, that takes all the possible issues in account.



Quote from: "Laurent"
try to enable this feature in sf::Sound too

I think it should be possible to implement it in sf::Sound in a similar way, too. But I'm not sure.
I might take a look into that class later.

Quote from: "Laurent"
think about how many loop points we want/can have

Best would be 2 points: loop start and loop end. More loop points would propably be nonsense.

Quote from: "Laurent"
should they be specified with a timestamp or a sample index?

A good workaround might be that the user can specify which format he uses - whether it's real time or sample index. For my preferences sample index should be best because it provides best precision.

Quote from: "Laurent"
if we have a "start" loop point, is it active right from the start, or only after the first loop?

A loop start point where the music will start is also nonsense, because then the user can discard the part before just from the audio file.
When playing the sound file, just start it from whereever it currently is (might be seeked by the user), and when it reaches the end of stream (or the loop end point) and loop is enabled at all, seek to loop start.

Quote from: "Laurent"
  • how to remove loop points? (using 0 or music.GetDuration() would not be reliable)
  • should we add a way to enable/disable loop points without removing them?

SFML already provides a function to enable and disable looping.
To remove loop points, a good way might be to set loop start and loop end to 0.

Quote from: "Laurent"
should we investigate metadata to see if we can enable loop points there for some audio formats, in addition to the C++ API

You mean, loop points stored in the audio file itself?
Please note that my previous display name was "Shy Guy".

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Enhanced Music Control
« Reply #9 on: February 21, 2012, 02:27:38 pm »
My point was to show you that even such a simple feature requires to take the time to think about it, gather use cases, talk to people who use it the most, etc.
Like I said I've never needed this feature, so there are probably other users who will have more relevant questions/suggestions/requests.

And when all these questions have an answer, then we need to make sure that the API is still simple and elegant.

Quote
I think it should be possible to implement it in sf::Sound in a similar way, too. But I'm not sure.

It's more difficult because SFML has no control over the playback, it's all done inside OpenAL.
And implementing the end point would be a complex task in sf::SoundStream too, because SFML only has the focus every N samples, where N is big enough so that the difference will be noticeable. Again, playback is controlled by OpenAL and it doesn't provide any way of inserting user code in it.

Quote
A good workaround might be that the user can specify which format he uses

That would make the API more complicated.

Quote
SFML already provides a function to enable and disable looping.

Is the end point still active when looping is off (ie. should the music stop there or continue until the true end)?

Quote
To remove loop points, a good way might be to set loop start and loop end to 0.

0 is a valid timestamp, therefore it is a bad candidate for a special value.

Quote
You mean, loop points stored in the audio file itself?

Yes, so that artists can set them. After all, it's not the programer's job.
Laurent Gomila - SFML developer

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Enhanced Music Control
« Reply #10 on: February 21, 2012, 02:35:32 pm »
Quote from: "Laurent"
Quote
SFML already provides a function to enable and disable looping.

Is the end point still active when looping is off (ie. should the music stop there or continue until the true end)?

In my opinion, if loop is disabled, loop points should be ignored and music will continue until the true end.
But let's see whether other people have different opinions.



Quote from: "Laurent"
Quote
You mean, loop points stored in the audio file itself?

Yes, so that artists can set them. After all, it's not the programer's job.

But is there a standard for some formats specifying the loop points?
For WAV there is, I think, but what's about OGG vorbis?
Please note that my previous display name was "Shy Guy".

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Enhanced Music Control
« Reply #11 on: February 21, 2012, 02:41:25 pm »
Quote
But is there a standard for some formats specifying the loop points?
For WAV there is, I think, but what's about OGG vorbis?

I don't know, that's why I said "investigate" ;)
I don't think that there's a standard that all audio formats would support, but if a non-negligible amount of them support metadata (probably in a different way), it could be an interesting feature.
Laurent Gomila - SFML developer

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Enhanced Music Control
« Reply #12 on: February 21, 2012, 03:01:07 pm »
Quote from: "Laurent"
Quote
But is there a standard for some formats specifying the loop points?
For WAV there is, I think, but what's about OGG vorbis?

I don't know, that's why I said "investigate" ;)
I don't think that there's a standard that all audio formats would support, but if a non-negligible amount of them support metadata (probably in a different way), it could be an interesting feature.

Hm, metadata... several formats support metadata at all, mostly only text. But I think alsmost none of them support loop points as "metadata".
Are you intending to allow, for example, a comment meta data "loop: 0-52596"?
Please note that my previous display name was "Shy Guy".

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Enhanced Music Control
« Reply #13 on: February 21, 2012, 03:02:09 pm »
Quote
Hm, metadata... several formats support metadata at all, mostly only text. But I think alsmost none of them support loop points as "metadata".
Are you intending to allow, for example, a comment meta data "loop: 0-52596"?

I have absolutely no idea. I haven't even had a look at them yet. That was just an idea to investigate.
Laurent Gomila - SFML developer

Tenry

  • Full Member
  • ***
  • Posts: 120
  • Experienced Programmer
    • View Profile
    • Simon-Burchert.com
Enhanced Music Control
« Reply #14 on: February 21, 2012, 03:16:36 pm »
Quote from: "Laurent"
Quote
Hm, metadata... several formats support metadata at all, mostly only text. But I think alsmost none of them support loop points as "metadata".
Are you intending to allow, for example, a comment meta data "loop: 0-52596"?

I have absolutely no idea. I haven't even had a look at them yet. That was just an idea to investigate.

I've worked myself with custom metadata in the PNG file for animations and also tried to find a way for OGG streams to define loop positions.

PNG is a very kind format, it allows so called "private" chunks, of which I can choose the inner format myself and I can store the number of frames in the PNG animation strip.

As for OGG I didn't find any convenient way to store such "user data". So I wouldn't "introduce" a way to store it in such a file format.
Please note that my previous display name was "Shy Guy".

 

anything