Vintage Soundsystem in game

Started by ASIKWUSpulse, March 21, 2018, 12:58:34

Previous topic - Next topic

ASIKWUSpulse

Hi, I'm looking for a way to playback music and sfx similar to how it was done on old game consoles and computers, where there was a limited amount of hardware voice-channels (each channel stereo or mono), and music & sfxs had to share playback-space. You'll remember that when a SFX was played, the instruments on the channels the SFX used were overlapped by the SFX sound, and then returning after the SFX was done with it's playback. I hope somebody can give advice on how I'm going to do. /ASIKWUSpulse

To be clear, I've made an illustration:
My favourite chord transition: Fmaj9 -> Gadd9 :D (I also like it's ±1 semitone variants)

LPChip

To my knowledge, those systems that supported it, was due to the hardware, not software.

Hardware that did not support it, would have dedicated music channels for sound effects, or simply categorize sound as unimportant and make that being muted, for a sound effect and wait until the next note plays.

The OPL sound chip from Yamaha had the first one, where the C64 SID chip had the second one. Only 3 channels, and if the game designer wanted an SFX, one of the 3 channel's sound would stop, and not play until the next note came along. This sometimes created a gap of sound, whereas with the OPL chip, it had, say... 4 channel polyphony with 6 channel virtual sounds. It could only play 4 channels at the time, but would move sound to one of the spare channels so it could make room for sfx. Sounds would play in order of priority, where, if more sounds were asked to play than polyphony would allow, it would not play it, or move its sound to a virtual buffer so it could start playing the moment the polyphony went down.
"Heh, maybe I should've joined the compo only because it would've meant I wouldn't have had to worry about a damn EQ or compressor for a change. " - Atlantis
"yes.. I think in this case it was wishful thinking: MPT is makng my life hard so it must be wrong" - Rewbs

ASIKWUSpulse

Oh, I actually didn't knew that type of playback method exsisted :O. I'm developing a programming method that will be my structure for old-console-inspired games, and I'm trying to come up with a way to mimic the sound from chips like the S-DSP (SPC700) in the snes, even the sound of when SFX-data mutes for some channels to play SFX, were the instrument will not be heard as you say until the next note. In my case, I need software to like "create a virtual soundchip", and I thought it would be easy since tracker modules are play-note-in-that-specific-channel-based
My favourite chord transition: Fmaj9 -> Gadd9 :D (I also like it's ±1 semitone variants)

Midori Mizuno

Wouldn't it be simpler/more faithful to compose actual SNES SPC music/SFX, incorporate it into your game, and playback that with SPC700-emulating library like this https://github.com/MrRio/js-snes-player/tree/master/snes_spc-0.9.0?

ASIKWUSpulse

#4
@MiDoRi I don't know if it's simpler, because there aren't many spc700 trackers or music sequencers that I know of, only Shiru's snes gss tracker, but it doesn't support the S-DSP built-in echo feature since the last version I used (I don't know if he's still developing it). Secondly, I use more than 8 channels, 14 channels to be exact and I use more than 64kbytes of samples.
My favourite chord transition: Fmaj9 -> Gadd9 :D (I also like it's ±1 semitone variants)

Saga Musix

I'm not even quite sure why you would want to emulate voice stealing (to me it's one of the most annoying mis-features of old sound engines), but assuming you were going to use libopenmpt, you can try setting the number of mixing channels to a very low value. However, even when using the libopenmpt_ext interface to play sound effects, those would still never steal any "foreground" music channels (i.e. actively playing notes), but rather it would try to steal channels from background (NNA) notes.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

ASIKWUSpulse

#6
Ok, so it works like that :/. For me, the "voice stealing" is somewhat important to remark that there is limitations, so it would sound exactly like the old pcm chips. But well, if that is hard to accomplish, then fine, it's not very important :). Thanks for the advices so far. The image in my first post is what I'm trying to accomplish, but the part with the sfx ovelapping music in some channels is not required, if it's like I said too hard to accomplish.
My favourite chord transition: Fmaj9 -> Gadd9 :D (I also like it's ±1 semitone variants)

Saga Musix

Here's my personal advice: Often it can be better to just focus on some limitations when working on a retro game and not emulate everything faithfully. People remember old games through rose-tinted glasses, meaning that they typically forget about some annoying details (difficult controls, long loading times from diskettes, etc.) but seem to remember all other details much more clearly (e.g. crisp digital sound). Of course your view may be entirely different and you remember voice stealing through those rose-tinted glasses, but I imagine that most people would find it annoying. I think it's way more important that the music and sound effects themselves are believable and have a retro vibe to them - especially because voice stealing is definitely something that has not happened in every game.
I think Thimbleweed Park is a great example for this phenomenon when it comes to its graphics - they make you really feel like you're an early-90s adventure game, they are nice and crispy, but at the same time they also have much higher fidelity e.g. due to true-color lighting effects. I think an analogy to music here would be that you have a great retro-sounding soundtrack, but use as many channels as required to still make it sound good.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

ASIKWUSpulse

#8
Ok, then that is the way to go :). Thanks. Is there a way though to playback specific patterns in mpt modules individually? Let's say that we load in a module somewhere in the source-codes initialization part, but have a playback function telling specifically that pattern to play and then return. Libopenmpt is the way to go, isn't it? since I know SDL_mixer only has suppot for .mod, and definitely not specific-pattern-playback. I agree aswell with Thimbleweed Park being a great example, it definitely has that low-res-style from old 90's computer games  8)
My favourite chord transition: Fmaj9 -> Gadd9 :D (I also like it's ±1 semitone variants)

Saga Musix

libopenmpt cannot currently play arbitrary patterns that are not part of the order list (e.g. if your order list "0 1 2 5", you cannot play patterns with ID 3 and 4), however if you add those single patterns explicitely to your order list (e.g. change it to "0 1 2 5 --- 3 --- 4") then you can change the playback position to those extra orders and libopenmpt will play those patterns. In this particular case, libopenmpt will also detect patterns 3 and 4 as stand-alone subsongs, and you can use libopenmpt's subsong mechanism to play them.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

ASIKWUSpulse

Oh, good. Now I only need to figure out how to use libopenmpt. Thanks again
My favourite chord transition: Fmaj9 -> Gadd9 :D (I also like it's ±1 semitone variants)

ASIKWUSpulse

A maybe funny maybe not so funny thing with this topic, was that one week later, I was so frustrated over not understanding audio-coding that I gave up. Guess I feel more at home in the game-coding node of the programming-world. I might by the way ask if somebody knows a good C++/C# IDE? since I think visual studio, telling by my 2-years experience of that IDE, is somewhat messy.
That is off-topic, so please post it here instead:
https://forum.openmpt.org/index.php?topic=6018.0
My favourite chord transition: Fmaj9 -> Gadd9 :D (I also like it's ±1 semitone variants)

Saga Musix

Quote from: ASIKWUSpulse on October 11, 2018, 08:17:10
A maybe funny maybe not so funny thing with this topic, was that one week later, I was so frustrated over not understanding audio-coding that I gave up.
Funny given that libopenmpt shields you from most of the actual audio coding. ;)
There are only a few audio concepts that need to be understood (e.g. whether the API you want to feed libopenmpt data into has a push or pull API), but I'd argue even that is something that should not be entirely alien to general game programming.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

ASIKWUSpulse

#13
Well, I tried learning it through thebennyboxs youtube-tutorial series Audio Programming Tutorial, but I thought it got really messy around the part where he writes to the audio callback, since he used the pulling-method I think :-\. There's a lot of data-conversions going on.
But I think I understand the ones we mostly use in C++ programming:

let's say we have 8 bits to play with, or a byte if that's better. Then the layout for the data-types would be like this:


// EDIT: noticed that 2^0 should also be here
// unsigned integer:
[2^7] [2^6] [2^5] [2^4] [2^3] [2^2] [2^1] [2^0] // = a scale of (0 - 255)

// signed integer:
[negative flag-bit] [2^6] [2^5] [2^4] [2^3] [2^2] [2^1] [2^0] // = a scale of (-128 - 127)

// unsigned float:
[2^3] [2^2] [2^1] [2^0] [2^-1] [2^-2] [2^-3] [2^-4] // = <don't know the scale of this>

// signed float:
[negative flag-bit] [2^2] [2^1] [2^0] [2^-1] [2^-2] [2^-3] [2^-4] // = <nor this>


I might have gotten somethings wrong
My favourite chord transition: Fmaj9 -> Gadd9 :D (I also like it's ±1 semitone variants)

Saga Musix

There is no such thing as unsigned floating point numbers. The internal representation of numbers is not really relevant here, it's an detail of the platform you are working on (and floating point happens to be much more complicated than what you described there, because the point of the number is, well, floating). All you need to know is how to convert the source audio to the target format; most of the time there is no conversion required: If your target API accepts floating-point, just pass floating-point samples as obtained from libopenmpt to it (nominal audio range is typically -1...+1, which is what libopenmpt gives you). If the API only accepts 16-bit integer formats (very rare these days), feed the 16-bit data from libopenmpt into it. Note that if you want to do the mixing yourself, it's much easier to do so using floating-point because it's almost impossible to overflow, while it's much more complicated with integer mixing.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.