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

Author Topic: Sound and Music common interface (SFML2)  (Read 6422 times)

0 Members and 1 Guest are viewing this topic.

Cody

  • Newbie
  • *
  • Posts: 5
    • View Profile
Sound and Music common interface (SFML2)
« on: February 04, 2013, 10:31:50 pm »
Hi,

I think a common base class for Music and Sound, providing public access to all SoundSource methods plus the playback methods could be handy in many cases.

In SFML 1.6 the class Music derived from Sound, but in 2.0 they have SoundSource as common base class. With that change it is now one has to provide two pieces of code, even if one only wants to play, pause and stop them. A candidate to reimplement that functionality is SoundSource. In this thread Laurent argued that SoundSource doesn't provide this functionality because it's purpose is to bundle common code. I understand that you don't want to pollute that class with abstract playback methods. Another, abstract class as interface that is implemented by Music and Sound would circumvent that problem.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #1 on: February 05, 2013, 03:18:49 am »
Can you give an example when such an interface would be useful?
Because in my opinion the two classes sf::Music and sf::Sound are quite different on what they play and how they play, thus it doesn't make sense to me to combine them or let them play independently. It would kind of be like sf::Image and sf::Texture would have a common interface.
sf::Music and sf::Sound are two different things and should be kept separated. But maybe there's a plausible use case I didn't think of. :)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Cody

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Sound and Music common interface (SFML2)
« Reply #2 on: February 05, 2013, 01:24:23 pm »
My use case is a game environment. Some environment sounds like e.g. a radio or rattling machines are very long running loops that are to expensive to be held in memory and thus are implemented as sf::Music. Other sounds like e.g. a bell or footsteps have less memory consumption and are needed repeatedly so they are implemented as sf::Sound that references a sf::SoundBuffer. Clearly the difference between sf::Music and sf::Sound is very important here. Once they are just "scene objects", the differences get unimportant. Both sound types may be bound to a scene node, both may be triggered by certain events etc.

To speak in terms of graphic objects, I think of something like the sf::Drawable and/or sf::Transformable class. A sprite, a circle and a text are at least as different as sound and music are. However they are all drawable and transformable objects. Likewise sf::Sound and sf::Music are both "spatialisable" and "playbackable" objects.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #3 on: February 05, 2013, 01:56:47 pm »
In your example, isn't it your responsibility to create this common interface? I mean, if I understand your design correctly, you'll have two SceneNode classes: SoundSceneNode and MusicSceneNode. Then how would it help if SFML implemented a common interface for musics and sounds, since you have to handle them separately anyway (because of how they work)?

I understand your point, but one of my priority in SFML 2 was to remove hierarchies of objects, virtual functions and polymorphism. I don't want SFML to be used as a framework, where you have to inherit certain interfaces to do things. I just want SFML to be a tool box, therefore the only inheritance that I kept is just to reuse common code, in order to avoid duplicating functionalities. You can argue about the sf::Drawable class being a pure interface with a virtual function, but it exists more for historical reasons and convenience, it's not really a strong design choice.
Laurent Gomila - SFML developer

Cody

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Sound and Music common interface (SFML2)
« Reply #4 on: February 05, 2013, 03:18:09 pm »
Well, what you described is how to handle the current SFML 2 classes. Although I'd introduce an abstract class AudioSceneNode from which the concrete classes derive. However if they had a common interface I'd only need one, non abstract, AudioSceneNode that references a sf::Sound or sf::Music through a reference of the common type. A builder then would provide a method to create an AudioSceneNode via either opening a stream or loading/reusing a sound buffer.

About your plan to remove hierarchies, virtual functions and polymorphism: From what I learned about object orientation that would mean removing object orientation. When removing runtime polymorphism and interfaces we're left with c-style structures using the c++ method call syntax. Or am I misunderstanding you?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #5 on: February 05, 2013, 03:29:43 pm »
Quote
Well, what you described is how to handle the current SFML 2 classes. Although I'd introduce an abstract class AudioSceneNode from which the concrete classes derive. However if they had a common interface I'd only need one, non abstract, AudioSceneNode that references a sf::Sound or sf::Music through a reference of the common type. A builder then would provide a method to create an AudioSceneNode via either opening a stream or loading/reusing a sound buffer.
If all the specificities of the sf::Sound and sf::Music classes are handled outside the scene node, and everything left there is the common part (playback and spatialization), then yes it makes more sense. But it's really not a big deal to have them separate, so I don't consider your use case to be convincing ;)

As I said, I don't want to do that anyway. But maybe in the future, if more feedback convinces me.

Quote
About your plan to remove hierarchies, virtual functions and polymorphism: From what I learned about object orientation that would mean removing object orientation. When removing runtime polymorphism and interfaces we're left with c-style structures using the c++ method call syntax. Or am I misunderstanding you?
I don't share your point of view. Object orientation just means that you design things as objects, an object being an entity which provides data and/or services (functions). And yes, you can perfectly have an object oriented design in C. Have a look at CSFML for example.

Public inheritance (and everything that goes with it) is a powerful tool, one of the most important in C++. But it doesn't mean that every C++ library has to use it. It introduces strong design dependencies in user code, so it's perfect for frameworks or final application code, but not for a lightweight tool box like SFML. Moreover, don't forget that SFML may be mixed with other libraries in user code; imagine if they all impose interfaces that have to be inherited etc., what a mess! I want users to have their own design, and only use SFML in their implementation part. I don't want SFML to drive their public API.
« Last Edit: February 05, 2013, 03:32:04 pm by Laurent »
Laurent Gomila - SFML developer

Cody

  • Newbie
  • *
  • Posts: 5
    • View Profile
Re: Sound and Music common interface (SFML2)
« Reply #6 on: February 05, 2013, 03:47:48 pm »
Quote
Public inheritance (and everything that goes with it) is a powerful tool, one of the most important in C++. But it doesn't mean that every C++ library has to use it. It introduces strong design dependencies in user code, so it's perfect for frameworks or final application code, but not for a lightweight tool box like SFML. Moreover, don't forget that SFML may be mixed with other libraries in user code; imagine if they all impose interfaces that have to be inherited etc., what a mess! I want users to have their own design, and only use SFML in their implementation part. I don't want SFML to drive their public API.

That is an admissible design choice. I've considered SFML a slightly more high level framework than the simple toolbox that should just provide a simple abstraction of openAL and sound file handling in case of the audio module. From that point of view the interface I proposed might not fit well into SFML.

However I'd still appreciate if it would be introduced to the api in the future.  ;)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #7 on: February 05, 2013, 03:59:05 pm »
Quote
I've considered SFML a slightly more high level framework
And that's what I'd like to avoid ;)
I know that this point of view may not be easy to understand, it's mostly a result of the experience I had with SFML 1.6.

Quote
However I'd still appreciate if it would be introduced to the api in the future.
Wait and see :P
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Sound and Music common interface (SFML2)
« Reply #8 on: February 05, 2013, 05:32:51 pm »
About your plan to remove hierarchies, virtual functions and polymorphism: From what I learned about object orientation that would mean removing object orientation. When removing runtime polymorphism and interfaces we're left with c-style structures using the c++ method call syntax. Or am I misunderstanding you?
It is a general trend in the C++ community to have a more distant look at inheritance. Other abstraction mechanisms, especially templates, are sometimes the better choice than a strict OOP pattern approach. The most powerful techniques arise as a combination of multiple abstraction mechanisms, such as type erasure which combines static and dynamic polymorphism.

In the C++ standard library, there is not much inheritance. The STL for example uses no inheritance at all, yet it is extremely flexible, much more than the Java collection counterparts for example. Simply because containers, iterators and algorithms are strictly separated. The place where inheritance is most often used are the I/O streams, and their design is rather old. It isn't necessarily bad, but I believe today people would design a I/O API differently.

An interesting example for modern idiomatic C++ is std::function. The classical approach for callbacks (including observer and command pattern) is an abstract interface with a virtual method, which is overridden by the concrete receivers of a message. This works, but brings the necessity to define at least two classes, to use dynamic memory management, and to abandon value semantics. C++ offers function objects (functors) which can act like functions and have value semantics. In C++11, the standard library introduced std::function, which can generically store global functions, member functions, functors and lambda expressions. We are now able to define a callback in one line, where traditional approaches required the definition of a whole messaging class hierarchy.

std::function is only one example, the tendency is visible in many areas. Inheritance is also today a powerful tool, but keep in mind that C++ offers much more, and rarely a puristic OOP approach as taught in design pattern or Java books is the best choice ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

dwarfman78

  • Full Member
  • ***
  • Posts: 228
  • I'm bietzsche, Nietzsche !
    • MSN Messenger - cd4c@hotmail.com
    • View Profile
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #9 on: February 07, 2013, 03:56:07 pm »
Nexus i think that what you say is lacking context.

I agree with you on that : inheritance from impl classes is almost always a bad idea, i'm always surprised to see people inherit from sf::Drawable for example...

The rest depends on your project's context.

The reasons why C++ is going away from strict OOP is because it can :

- C++ is a performance driven language.
- C++ developers are fewer and often better, they are trained to know what they do with memory.
- C++ projects are most of the time smaller.

this mean that you can sacrifice some "tidiness" to gain speed (code writing or runtime speed).

Java is sticking (sticky sticky) to strict OOP because :

- Java is maintenance driven. (performance rarely matters in professional java applications)
- Java developers are often bad developers, because many many developers are needed they cannot be all top devs.
- Java projects are big, they need to use simple paradigm because business processes behind are hard to understand.

From a personal point of view, i prefer seeking a seemingly useless 10 lines class for a bug than seeking for a "lost" callback function lost somewhere out of any context/concept or lost somewhere in memory (remember devs are dumb they need safety).

You also seems to forget that strict OOP includes interface implementation and not only abstract/implementation class inheritance.

Most of the time you can replace inheritance with composition too.

I think what you say about Java collections is wrong, those design flaws comes from first versions of the language and not from some lack of features.

You could easily rewrite collections in Java language with weak coupling between containers/iterators and algorithms.
« Last Edit: February 07, 2013, 03:59:39 pm by dwarfman78 »
@dwarfman78
github.com/dwarfman78

dwarfman78

  • Full Member
  • ***
  • Posts: 228
  • I'm bietzsche, Nietzsche !
    • MSN Messenger - cd4c@hotmail.com
    • View Profile
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #10 on: February 07, 2013, 04:05:37 pm »
I realize that i'm deviating from the original subject and i apologize for that.
@dwarfman78
github.com/dwarfman78

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #11 on: February 07, 2013, 04:07:09 pm »
What's wrong with inheriting from abstract interface class?(drawable is abc)
Back to C++ gamedev with SFML in May 2023

dwarfman78

  • Full Member
  • ***
  • Posts: 228
  • I'm bietzsche, Nietzsche !
    • MSN Messenger - cd4c@hotmail.com
    • View Profile
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #12 on: February 07, 2013, 04:22:19 pm »
What's wrong with inheriting from abstract interface class?(drawable is abc)

my bad i was talking about an old implementation of Drawable from SFML 1.X sf::Sprite :) often saw with multiple inheritance...
« Last Edit: February 07, 2013, 10:21:21 pm by dwarfman78 »
@dwarfman78
github.com/dwarfman78

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Sound and Music common interface (SFML2)
« Reply #13 on: February 07, 2013, 04:59:06 pm »
It's normal to inheirt transformable too, most of sfml does. It makes more sense to do that and call getTransform() in own draw() than require transforming from user or reimplement every single setxxx and getxxx and overloads to take vectors and floats every single time.

Quote
my bad i was talking about an old implementation of Drawable from SFML 1.X sf::Sprite :) often saw with multiple inheritance...
« Last Edit: February 07, 2013, 09:21:21 PM by dwarfman78 »
Oh.. well, yeah that often doesn't make sense. :)
« Last Edit: February 08, 2013, 11:21:29 am by FRex »
Back to C++ gamedev with SFML in May 2023

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Sound and Music common interface (SFML2)
« Reply #14 on: February 09, 2013, 01:30:28 pm »
Quote from: dwarfman78
this mean that you can sacrifice some "tidiness" to gain speed (code writing or runtime speed).
The alternative to dynamic polymorphism is not necessarily faster. Consider std::function, it needs to dispatch dynamically too, either through virtual functions or function pointers. Static polymorphism can be faster, but it requires knowledge at compile time. By the way, the main reason I use modern C++ features is not speed, rather the possibility to apply powerful and expressive concepts.

Also, I don't really think it's less tidy. Of course, functionals are more difficult to understand initially, but once this is done, they can simplify things a lot (less code and fewer classes to maintain). Concerning debugging, you can track a callback the same way as a called virtual function -- only that the callstack may contain some levels of the std::function implementation itself, but they can be skipped.


Quote from: dwarfman78
I think what you say about Java collections is wrong, those design flaws comes from first versions of the language and not from some lack of features.
They resulted to one side because the language lacked features (initially there were no generics, it's still possible to use untyped collections) and still lacks (global functions like the STL algorithms are not possible, instead much functionality is duplicated for each collection type; because of no const, new unmodifiable objects must be created). Also, there are severe design flaws resulting from bad OOP and LSP understanding (Stack inherits Vector).

Interfaces are nice in many situations, but they have some problems: They cannot contain state or implementation, so if multiple classes implement the same interface and have partially the same data or functions, code duplication is necessary. Also, the only way to abstract from multiple classes is to let them implement the same interface; if you cannot change the classes, you're lost (meaning you have to write further adapter classes). The mere existence of UnsupportedOperationException shows the limits of interfaces pretty well, it introduces weakly typed elements. At least generics improve the situation slightly, but it's well visible that they are put on top of the existing language and do not integrate very well.

To sum up, Java is a good example to show the problems of using class hierarchies as the primary way of abstraction. The whole discussion is not as simple as "strict OOP = better maintenance but worse speed", a lot of unconventional C++ features improve also maintenance and debugging.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: