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

Author Topic: "intro" and "loop" portions in BGM  (Read 10578 times)

0 Members and 1 Guest are viewing this topic.

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
"intro" and "loop" portions in BGM
« on: April 17, 2010, 06:57:00 am »
Hello all.  I'm new to SFML and have been skimming the documentation and forum.

There's one basic feature that the Audio lib really should have that I can't see how to do in the documentation.  Nor can I find a thread that [reasonably] solves the problem.

For BGM that loops, how can you specify an "intro" portion, or a "loop" portion.  Basically if you have some BGM that has a 5 second intro that you don't want looped, but you want the rest of the BGM looped.... how can that be accomplished?

I don't see a way to make it happen with the Music class.  Am I just not seeing it?

Thanks!

Ashenwraith

  • Sr. Member
  • ****
  • Posts: 270
    • View Profile
"intro" and "loop" portions in BGM
« Reply #1 on: April 17, 2010, 07:55:37 am »
You split your song into two different sound files and play them separately?

That seems to make the most sense because otherwise you are going to have to mark segments for streaming and that gets messy.

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
"intro" and "loop" portions in BGM
« Reply #2 on: April 17, 2010, 08:00:19 am »
Right but how do you get the loop file to play immediatley after the intro file?

I'd want to-the-sample perfection on the transition.  Any kind of
Code: [Select]
if(intro.end) loop.start() solution is going to take CPU attention, and will have a delay between when the intro stops and where the loop begins.

This would have to be functionality built into the Music class.

Anyway -- after looking at the Music source, it seems really straightforward, so I've begun to modify it to create a second class which has this functionaltity built in.  I should have a very rough (but working) class by tonight, and I'll polish it up tomorrow.

I'll post my results either tonight or tomorrow depending on how many snags i hit.

EDIT:

Success!

Preliminary testing works.  Now I just have to touch up the code and look out for error conditions.

Oh and come up with a better name for the class.  Right now I have "Music2" which is incredibly lame.  If anyone has suggestions for a better name, I'm all ears.

Basically the class works the same way Music does, only you give it two files instead of one.  One is for the "intro" part, and the other is for the "loop" part.  It'll start playing the intro portion, and when it reaches EOF it will immediately switch to the loop portion (on the sample, so it's a sample-perfect transition.  No gaps or overlaps).

Rather than post it all on here, here's the pastebin links:

http://pastebin.com/taPJXQ5Y   <-  Music2.hpp
http://pastebin.com/SaaVA9ge   <-  Music2.cpp

Note:

WORK IN PROGRESS.  It doesn't really do any error checking and there are a million ways to make it break or play incorrectly.  DO NOT USE IN A REAL PROGRAM YET.  Like I said I'll touch it up and bulletproof it tomorrow, but it's too late tonight.


What are the odds of this getting added to the official SMFL distrubution once completed?  Surely this must be a common request from people.

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
"intro" and "loop" portions in BGM
« Reply #3 on: April 17, 2010, 06:26:28 pm »
Well if anyone is interested I finished it up:

http://pastebin.com/qhBwcmmg  <- Music2.hpp
http://pastebin.com/jvwq7H75  <- Music2.cpp

Things to note:

-  The SetLoop() value is disregarded completely.  The "Intro" portion never loops, and the "Loop" portion always loops.

- You can have an Intro portion and no Loop portion or vice versa.  Just pass an empty string or a null pointer when loading the data.  If you do not have a Loop portion, the Intro will play once and stop.  If you do not have an Intro portion, the Loop portion will play and loop.

- GetDuration returns the duration of both files.  Although it's kind of pointless because if you have a Loop portion it will loop forever.  Part of me wanted to make GetDuration return positive infinity if a Loop portion is loaded but I figured that wouldn't be very useful.

- If you have both an Intro and a Loop portion, the files must have the same samplerate and channel count.  Mixing a mono Intro with a stereo Loop will result in load failure.

- I'm still open to suggestions for a better name for the class.  I'm still using "Music2" and it's still just as lame of a name.

So yeah.

I'm very interested in feedback.  Something like this almost seems like it should be fundamental in an audio lib.

Can we expect this (or something like it) to be implemented in future versions of SFML?


EDIT:  minor correction to OnStart

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
"intro" and "loop" portions in BGM
« Reply #4 on: April 17, 2010, 06:47:14 pm »
Quote
Can we expect this (or something like it) to be implemented in future versions of SFML?

No ;)
But maybe I can think of a way to make it much easier to implement, so that at least you don't have to use SFML's internal classes.
Laurent Gomila - SFML developer

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
"intro" and "loop" portions in BGM
« Reply #5 on: April 17, 2010, 06:58:19 pm »
awww   lame   :P

I guess I'll just have to use a modded SFML then.  At least until it can be implemented some other way.

C'est la vie.

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
"intro" and "loop" portions in BGM
« Reply #6 on: May 04, 2010, 05:43:26 pm »
Quote from: "Laurent"

No ;)
But maybe I can think of a way to make it much easier to implement, so that at least you don't have to use SFML's internal classes.


I thought I would resurrect this as I strongly feel this is worth reconsideration.  Most games have BGM which behaves this way, and lack of support for this in SFML is a significant shortcoming, IMO.  Especially when a possible solution is so simple.

What disadvanges are there to a Music2-style class?  I could maybe understand not wanting to implement something like this if it damaged the API somehow.  Granted, this is slightly inconsistent with the way it changes loop behavior, but that could be worked around (I just didn't bother with it because I was aiming for something functional).

I honestly thought this was a decent solution, but instead of being met with consideration, it was just immediately dismissed.  It's not that my pride is hurt or anything, I'm just wondering why?


As for other potential solutions:  I'm open to whatever works.  This would have to be something done in immediately by the SFML's classes though... or support for it would have to be extended outward somehow.

The only other way I can think of would be to have sf::Music have a callback mechanism, where it could alert the program that one song has ended, so it could switch to another one.  But this solution is not ideal because:

1)  Callback interfaces are much more difficult to work for the end user.
2)  It introduces threading issues to a program that may or may not be threadsafe.
3)  It would require some heavy internal changes as to how sf::Music works.


As it is right now, this is something that can't be done with SFML out of the box, and it's something that many if not most games will want to do.  This really should be among the top priorities for things to add to SFML.

I'm interested in hearing your response.

Thanks!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
"intro" and "loop" portions in BGM
« Reply #7 on: May 04, 2010, 06:28:06 pm »
You're absolutely right, but I have to think more about it before giving you an answer.

I don't really care about technical stuff (it is always possible -- and often easy -- to implement features), I just want to keep the API simple, clean and consistent. Having a good design is much more important than making things work and available.
Laurent Gomila - SFML developer

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
"intro" and "loop" portions in BGM
« Reply #8 on: May 05, 2010, 04:04:02 am »
Quote from: "Laurent"
I just want to keep the API simple, clean and consistent. Having a good design is much more important than making things work and available.


I agree 100%

Let's look at this another way.  From what I see there are 3 things about Music2 that make it weird/inconsistent/incompatible with the existing API:

1)  It requires that both intro and loop portions share the same channel count and samplerate.

2)  It bypasses the existing loop system and implements its own looping

3)  The duration calculation is a little strange.


If all 3 of these points could be addressed, then maybe this would be something easier to implement.

So let's look at possible solutions:

1)  Unfortunately, I don't think there is a solution for this.  Not unless you build in some kind of resampler which would be more trouble than it's worth.  On the plus side, this limitation doesn't really make the API inconsistent, so it's not that big of a deal, imo.

2)  The main reason for this is because, as far as I can tell (and I might be wrong as I haven't extensively looked at the code), SoundStream::OnStart() is called to implement the looping in derived types.  This is a problem for Music2 because starting and looping will have 2 different results.

The fix for this would be to create a virtual OnLoop() function in SoundStream, and to modify the looping code to call OnLoop instead of OnStart when it needs to restart the loop.

This would require changes to SoundStream which is why I didn't go this route in my original attempt.  I was going for an "as few changes as possible" quick-fix.  But for a more long term solution I think this is the way to go.

Other derived types wouldn't need to be changed.  SoundStream::OnLoop could just call OnStart by default, and only derived types that need different behavior (ie:  Music2) would re-implement both.

I think that overall, the changes to make this work would be very minor and wouldn't impact the API or overall design very much.  And after the changes are made, the existing looping system will work as expected in Music2.


3)  I guess the solution for this depends on what you define the "duration" as.  Is it the duration of the portion that loops?  Or is it the duration of the whole thing until it starts looping?  My code interpretted it as the latter.  Although I'm not sure if that's what you had in mind.

If worse comes to worse you could make 2 durations.. like a loop duration and a full duration, and have different functions to return each.  But that's getting into messy API changes that probably aren't a good idea.



Just throwing ideas out there.  Like I said I'd really like to see this or something like it get implemented in SFML 2.0.  I think it'd be a big improvement.  Once you have some time to think about it, I'd be very interested in hearing your thoughts.

Thanks for reconsidering!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
"intro" and "loop" portions in BGM
« Reply #9 on: May 05, 2010, 09:00:12 am »
The problem is not in the details, it's the class itself. SFML aims to provide building blocks: playing a sound, streaming a music, ... but not "streaming an intro music then a another one that loops". It's like image managers, most people need one but SFML will never provide it directly.

In my opinion, the real problem is that the audio module is not flexible enough. Maybe it's just a matter of making the SoundFile class publicly available, I don't know. Anyway, I think that solving this limitation will be much more interesting than adding a Music2 class.
Laurent Gomila - SFML developer

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
"intro" and "loop" portions in BGM
« Reply #10 on: May 05, 2010, 04:51:38 pm »
Quote
Maybe it's just a matter of making the SoundFile class publicly available


I get it.  That way you can derive your own SoundFile type which acts as two different sound files.. rather than have a Music2 class which plays two different files.

That could work.

It's probably not a bad idea either for expandability purposes.  That way people could add in support for additional audio files types that might be obscure (nsf/spc or the like).

It might also open the doors to 3rd party contributors that expand SFML's core functionality.  Kind of like SDL_Image and SDL_Mixer.  (But whether or not that's a good thing or something you want for SFML is another matter.  Personally I'd welcome it).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
"intro" and "loop" portions in BGM
« Reply #11 on: May 05, 2010, 05:07:15 pm »
Quote
I get it. That way you can derive your own SoundFile type which acts as two different sound files.. rather than have a Music2 class which plays two different files.

Ah, this is not what I had in mind. This cannot work: how would you tell sf::Music to use your own derived SoundClass?

I was thinking about making sf::SoundFile available because this is the only thing that prevents you from implementing the Music2 class without using SFML's internal classes. With sf::SoundFile available, you can create your own sf::SoundStream that looks like sf::Music but that handles properly the intro and loop. Well, in fact I guess this is exactly what your class does :)

Quote
That way people could add in support for additional audio files types that might be obscure (nsf/spc or the like).

This will be the job of the plugin system that I have to implement in SFML 2.
Laurent Gomila - SFML developer

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
"intro" and "loop" portions in BGM
« Reply #12 on: May 08, 2010, 08:55:54 am »
Quote from: "Laurent"
I was thinking about making sf::SoundFile available because this is the only thing that prevents you from implementing the Music2 class without using SFML's internal classes.


This sounds like it could be a winner then.  It would certainly solve my current problem.

Will sf::SoundFile be public in SFML 2?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
"intro" and "loop" portions in BGM
« Reply #13 on: May 08, 2010, 01:49:30 pm »
Quote
Will sf::SoundFile be public in SFML 2?

I have to think about it more, but anyway there will be a solution for your problem, yes ;)
Laurent Gomila - SFML developer