Hi there.
I was just wondering if it would be possible to create soundtracks with AGS a la the iMuse system LEC uses in their games from MI2 and forth.
For those of you who are not familiar with the iMuse system I'll try to explain:
The music in the town (or whatever) Woodtick in MI2 is buildt up around a reggae loop. But when you enter one of the ships the music expands (eg. more instruments are added to the beat). There's even a bar of variation before it changes. The best thing about this is that the music changes by the bars so that the first loop ends before the next continues. That means you get the feeling that the music never change or fade out.
I hope I'm being clear enough here...
Thanks...
Possible. Using the timer functions and the goto functions for midis it would be possible. I'll help, pm me.
iMUSE clearly took advantage of synthesized music, and Monkey Island 2 was the tech demo for it. I don't think AGS has the ability to control the instruments for midis or the other supported synth formats.
I bet a module could be written for digital music that does an effect similar to what was done in curse of monkey island. It wouldn't be the same because it would be for digital music, but it would still be dynamic music changes, you know? that would probably make vox files a lot bigger...
Search this board. I remember a topic like this a long time ago. The net result was, yeah, it was sorta possible, using - as Elliott suggested - the "goto functions for MIDIs", aka the SetPos and GetPos thingie.
There's also the DirectMusic plugin (http://www.adventuregamestudio.co.uk/yabb/index.php?topic=13531):
Quote from: modgeulator on Wed 28/04/2004 09:12:50
It's intended for playback of DirectMusic Producer soundtracks. You can create scripted interactive music in DMP and use this plug-in to load your project and call routines from within AGS.
If you've ever paid attention to the music in LucasArts games, from Monkey Island 2 onwards, you should have noticed how the music is constantly changing depending on what you do in the game. Think of the music in Woodtick, or at the swamp/voodoo lady. If you can learn DirectMusic Producer, you can now have music like that in an AGS game.
I thought that plugin was in beta phase still! I must add it to my site!
It sounds like it is not quite finished:
Quote from: modgeulator on Thu 19/08/2004 07:42:07It's still being worked on occasionally. That said, I don't think it's ever going to have any sort of appeal to anyone other than myself, so I'm wasn't planning on releasing anything else publicly. If anyone wants to use DirectMusic for their game they can feel free to message or email me and I'll give them what I have and any other assistance I can provide.
DirectMuse seems like a pain to work with too.
I'd do it like this:
music1.mid
music2.mid (transition)
music3.mid
room1 plays music1
room2 has in rep_ex
if music 2 is not playing
check if it's already played, play music 3 otherwise
if (getpos(music1 pos1) || (etc with a few break points))
{
PlayMusic(music2);
}
messy pseudo-code, sorry
You can do something like that with scripting in AGS pretty easily. The GetMidiPosition() function returns the current beat so, for example when you want to transition, if you have a 4/4 piece of music, just set it up in repeatedly_execute_always to wait until the current beat is divisible by 4, play the transition music and use PlayMusicQueued to que the next piece. You can also do this with digital audio music tracks: you just need to calculate the tempo and time signature in such a way as to determine the length, in milliseconds, of each measure.
Unfortunately, both ways suck ass when you actually try them out. The problem is the music totally glitches when you stop and start another track. The notes all cut off in a very obvious and unpleasant way and for some reason it ALWAYS plays some notes from further along in the track. With digital audio unfortunately the functions don't seem to be terribly accurate, so you'll get it half a beat on or off or so everytime it transitions.
So yeah, you can script iMuse-ish transitions and stuff in AGS, but it will glitch really badly when it plays them - thus negating the whole point ::)
There's two big problems with my simple little plugin:
1) It doesn't work alongside AGS DirectSound
2) You have to put everything together in DirectMusic Producer, which is a notoriously un-user friendly and buggy bit of software. Sorry about that ;)
QuoteWith digital audio unfortunately the functions don't seem to be terribly accurate, so you'll get it half a beat on or off or so everytime it transitions.
It's not the accuracy of the functions as such transitions work beautifully with .wavs - it's something to do with the compressed audio decoders.
Quote from: Adamski on Wed 26/10/2005 11:27:50
QuoteWith digital audio unfortunately the functions don't seem to be terribly accurate, so you'll get it half a beat on or off or so everytime it transitions.
It's not the accuracy of the functions as such transitions work beautifully with .wavs - it's something to do with the compressed audio decoders.
Very interesting. So if you distribute the music in a compressed format and have it decompress to wav's as part of the installation process you'd be in business for a working iMuse-ey soundtrack completely scripted withing AGS? Cool :D
Of course it'd mean the players would need several hundred megabytes free space for the game, but that shouldn't be much of a problem these days should it?
It would be a very heavy-handed way of doing things, but I guess you could do. I mean, you can already crossfade audio tracks in AGS so if you can live without syncronised crossfading to get that "same track, different instruments" effect then it's not really worth doing.
Perhaps there's still something that can be tightened up within AGS to allow this to be done - perhaps some extra variable in the Seek and Get functions to compensate for the decoding? I've been pushing for this since the Dos days so it'd be nice if it could be done flawlessly :)
Just tried to do an experiment with this but it doesn't seem that AGS will play wav files as music?
Also, I have a feeling the inaccuracy is a problem within Allegro.
I think CJ took out packing wavs into the .vox file for the sake of sensibility, but if you put the .wavs in the compiled folder it works fine.
Thanks, that way works.
.OGG produces seamless loops, much like wav. But it's a lot smaller
Quote from: Adamski on Wed 26/10/2005 12:59:53
Perhaps there's still something that can be tightened up within AGS to allow this to be done - perhaps some extra variable in the Seek and Get functions to compensate for the decoding? I've been pushing for this since the Dos days so it'd be nice if it could be done flawlessly :)
Unfortunately I'm not sure how practical this is. The music is decoded in chunks and if you seek to a specific position then the decoder seems to need to decode the whole chunk that you're in, which leads to the effect that you describe.
PreloadChunk(int milliseconds, BlockingStyle blocking)
could PlayMusic and SeekMP3PositionMillis have an optional variable to excecute the crossfade and seek to the time defined until the chunk is decoded?
Even a game with a pretty hefty soundtrack (for an amateur game at least) of an hour or so would only take 600mb hard drive space. Obviously it would be preferable to be able to leave the soundtrack in a compressed format, but would it really so be terrible to have to decompress to .wav files - considering all the cool stuff the composer could now do? Just asking because I'm keen to write a module for dynamic soundtracks using uncompressed .wav files, would anyone actually be interested in using it?
It's too terrible to have a bunch of uncompressed Wave files lying around in a game's folder.
IMO 10MB is large enough for a very large game already, 600MB...
Well, to me 600 MB doesn't seem like that much, but my latest drive has 200 GB :)
I am thinking of an alternative method that might work if the MP3/OGG always plays at the correct rate. For example:
----
PlayMusic( some MP3 file # here)
StartPreciseTimer //A plugin could do that - precise timing to better than ms precision. AGS' GetTime function is only precise to seconds.
//Somewhere in RepEx:
If (PreciseTimer >= some position) PlayMusic( the other music file #)
----
A significant caveat there is that if the player switches (Alt-Tab) out of the game, the music is paused, so your timing would be way off. But perhaps then GetMP3PosMillis() could be used to check the other timer's validity?
Hmmm... an intersesting idea, but I don't think the music and timer would start at exactly the same time. And, even if you could get a timer to trigger the change at the exact right millisecond I think there are issues with the very nature of compressed audio playback that would still cause it to glitch badly.
I think to get a system like this working with compressed audio would require some clever pre-caching trickery...
And there's an even bigger issue if using scripting to start the other track - with a game speed of 40 fps, that's 25 ms per frame, so that limits the accuracy of starting a track to +- 12 ms or so; and it wouldn't matter if it's a WAV or MP3.
This (again) points towards using a plugin instead. But perhaps it could play digital sound instead of using directmusic producer?
Quote from: Elliott Hird on Wed 26/10/2005 19:03:40
PreloadChunk(int milliseconds, BlockingStyle blocking)
That sounds a bit too low-level for a script language.
Here's a quick little demo I put together using .wavs to show how I envision this working...
http://iinet.net.au/~snderson/musictest.exe
(self-extracting rar, please make sure to extract this to a new folder)
In my computer (Athlon 1800 2800Mhz), it takes some time from track to track.
On the matter of quality for the composer:
When you compress a music file from WAV to MP3 cor OGG, you kinda fuck with the waveform. So uncompressing it will create a bad quality for the music. MP3s are good only for transfering purposes. If you turn an MP3 back to WAV (or AIF), you get poor results. Just my little thought, since I'm a composer.
600mb just makes your game look cool :P. PM me modgeu-thingymabob, I think I can be of help.
Quote from: Nikolas on Thu 27/10/2005 10:39:21
In my computer (Athlon 1800 2800Mhz), it takes some time from track to track.
In what way does it take time? It's meant to wait until the end of the measure before changing if that's what you mean. Or do you mean that it pauses and the sound breaks up?
BTW, it's impractical to distribute with uncompressed WAV files - I convert from OGG back to WAV not for sound quality but so the position in the file can be tracked accurately during playback (as was discussed extensively in this thread already.)
I agree with Gilbot, there's no way I'm going to distribute a freeware game that uncompresses to 600mb, especially if the music's been lossy-compressed.
Also Nikolas, I think your explination of lossy-compressed music is a bit... lacking :P Obviously uncompressing an OGG or MP3 will not put back in the data it chopped out when compressing, but it won't necessarily be 'bad quality'... unless you compressed at 64kbp/s or something silly.
Anyway, I think the point is to not get worked up over this niggling issue to the point of surprising people with games that uncompress to half a gig. You can still do crossfading and lots of cool little iMuse things without needing to syncronise two tracks.
Your tech demo was pretty impressive - I found that turning the sax solo on/off worked fine, and the "transition to variation" too. However, with the "transition back" button, there was a little silent pause before the first tune started up again.
I wonder, would your method still work if only the short transitions were WAVs, with the longer tunes kept compressed?
Thanks. The pause before the tune kicks back in was deliberate, it was intended to sound like that. If it sounds a bit wonky it's because I put it together quickly just to see if it would work more than a problem with the system itself. Thanks for the feedback, btw what speed computer were you using? I'm working with an Athlon 2800 and haven't tested it on anything slower.
Quote from: Janik on Fri 28/10/2005 01:13:39
I wonder, would your method still work if only the short transitions were WAVs, with the longer tunes kept compressed?
No, you need to be able to track the position in the song you want to transition from accurately - it possibly would work the other way around (only compressing the transitions), but that wouldn't help very much with the size problem.
I tried it at work with a P4, 2 GHz, and at home with my Athlon 64 3500+; it worked the same on both computers, as far as I could tell.
Quote from: modgeulator on Thu 27/10/2005 11:20:53
In what way does it take time? It's meant to wait until the end of the measure before changing if that's what you mean. Or do you mean that it pauses and the sound breaks up?
BTW, it's impractical to distribute with uncompressed WAV files - I convert from OGG back to WAV not for sound quality but so the position in the file can be tracked accurately during playback (as was discussed extensively in this thread already.)
There is a slight loss of rhythm. When I press the sax button there is a very slight delay and with the transition button it is the same.
I know why you had to uncompress the music files.
I'd love to have this options as a composer, don't get me wrong. One problem I have, as mentioned before I think, is that it's strange to have a game of 10-20 Mb and the music be 600!
@Adamaski: I checked it a bit further. I believe that there is actuall further loss when you decompress. At least this is what I hear and this is what I see in the waveforms. I checked the original WAV file, the MP3 at 128 Kbps and the MP3 back to WAV. Everything done to Cubase at the highest quality (and slowest). The WAV files have 1411 Kbps, thus enhancing the "wrongs" of the MP3. You can see that there are differences in the waveform. I don't think that it's alot but anyway, just my thoughts (which are a bit off-topic). It's just that I would love to make proper music files for games but webspaces does not permits us to do that... :(
Quote from: Nikolas on Fri 28/10/2005 03:23:38
There is a slight loss of rhythm. When I press the sax button there is a very slight delay and with the transition button it is the same.
Yeah, for some reason when you use SeekMP3Position() on a wave file it seeks to a sample (I think) instead of to a millisecond - so I had some difficulty compensating for that.
Quote from: Nikolas on Fri 28/10/2005 03:23:38
@Adamaski: I checked it a bit further. I believe that there is actuall further loss when you decompress. At least this is what I hear and this is what I see in the waveforms. I checked the original WAV file, the MP3 at 128 Kbps and the MP3 back to WAV. Everything done to Cubase at the highest quality (and slowest). The WAV files have 1411 Kbps, thus enhancing the "wrongs" of the MP3. You can see that there are differences in the waveform. I don't think that it's alot but anyway, just my thoughts (which are a bit off-topic).
But when you playback audio you're decompressing it, it sounds like there was something iffy in the algorythms used in one of the programs you tried with.
I had an idea. I don't know nothing about AGS and how to do it, but I was thinking this:
If you had a track at lets say 120 bmp and you wanted to smoothly take it to other places without breaking the track at all, right? You could keep this track in MP3 format and have another "empty" track in WAv form. The second WAV form could be only one bar. This way you wouldn't need to track the MP3 or make it into WAV, thus wasting space and quality (according to me, which is not the issue here), but you could track the WAV file which would be noiseless and only 1 bar. This could give you the exact place of where you're playing. And if you could loop this 1 bar you could see if it has been looped 4-6-8-16 times and thus keep your melody into place.
Could this work?
Yeah, I was wondering about something like that. The first problem is that you can only play one music track at a time. Second problem is that there would be a varying delay introduced everytime you try to play two sounds at the same time that would only make matters worse.
Anyway, I had another little play around with MIDI files and I found that you can transition smoothly from one to another, but you have to edit the MIDI so that everything is offset by about a 32nd beat, so that nothing from the next measure is played when you change MIDIs. I'm thinking of putting together a simple little module for this, if anyone is still interested in working with MIDI.
Quote from: modgeulator on Mon 31/10/2005 13:17:17
Yeah, I was wondering about something like that. The first problem is that you can only play one music track at a time.
About the first problem I believe that you can have more than one audio files playing at the same time. Like if you have fx along with music. I think it has something to do with different channels or something. Sorry for not being able to be more helpful. I find very interesting what you're trying to do... :)
PlaySound(int sound, int channel) :) just name the blank one soundx.wav :)
QuoteThe music is decoded in chunks and if you seek to a specific position then the decoder seems to need to decode the whole chunk that you're in, which leads to the effect that you describe.
I'm not sure if it'll make any sense, but could we know how long these chunks are (or don't they have a constant length)? I would try to make the game wait until the MP3/Ogg/whatsoever is at the end of such a chunk and then start the transition, so there wouldn't be any delays then.
I noticed that sometimes the transition is accurate and sometimes it isn't. So I concluded that the delay depends on where you currently are in one "chunk" (lovely word). Early means big delay, the nearer to the end, the smaller is the delay. Did I misinterpret this?
Quote from: Nikolas on Mon 31/10/2005 12:46:29
You could keep this track in MP3 format and have another "empty" track in WAv form. The second WAV form could be only one bar. This way you wouldn't need to track the MP3 or make it into WAV, thus wasting space and quality
Since we don't need to fade it, couldn't the empty track be a midi, so we wouldn't (at least i hope) slow the engine? Using a wav could work, but if we're also using fx, it could be a problem.
Vel and I tried to do this very thing with the freeware version of Shivah. During the final fight scene, Vel had this neat idea to add extra layers to a music track as the hero got closer to victory, and to remove them as he got further away. Unfortunately, I could never get it to work. The tracks would never synch up properly, and even cross fading sounded weird and wrong. So we scrapped the whole idea. A shame, really, since Vel put all that work in.
So has anyone had success doing this? modgeulator seemed to get pretty close, but I haven't heard of any progress...
Maybe I didi it! Just need to improve the script...
I'll post it as soon as I finish ;)
Ok, i definitively did it!
To override the break we all heard, i fade out music1, then fade in music2 strating where music1 was. (it works with oggs, mp3, and wave; i haven't tested it on midis but it should work if you use getmidiposition instead of getmp3posmillis)
Here is the code:
first of all put this at the beginning of the script:
int fade_switch=0, timer=0, music, mp3pos,vol;
then import the same variables into the haeder.
put this into repeatedly_execute:
if (fade_switch==1) {
timer++;
if (timer<=100) {
SetMusicMasterVolume(100-timer);}
if (timer>100){
if (timer<=150){
SetDigitalMasterVolume(100-(timer-100));
mp3pos=GetMP3PosMillis();}
if (timer==151) {
SetMusicVolume(-2);
PlayMusic(music);
SeekMP3PosMillis(mp3pos);}
if (timer>151){
if (timer<=200){
SetDigitalMasterVolume(50+(timer-150));}
if (timer>200){
if (timer<=300){
SetMusicMasterVolume(0+(timer-200));}
if (timer==310) {
SetMusicVolume(-1);}
if (timer==320) {
SetMusicVolume(0);}
if (timer>320) {
fade_switch=0;
timer=0;}
Ok, this is the code; now let's check the variables:
"fade_switch" is the switch that make the music change;
"music" is the music number;
to make the music change (in a room, an interaction, or wherever you want) turn the switch on (fade_switch=1), and set "music" to the number of the incoming song (i.e. music=2 for music2.ogg)
Of course you can change fade velocity, just make some calculation :)
If you're gonna use the code I'd appreciate to be in your credits, but you don't have to :P
Edit by strazer (Please use the Modify button instead of double-posting.):
I forgot: the only problem is you can't let the player set the music volume, because the script wouldn't work :( ; anyway it's easy to solve it, i'll do it (not today :P).
oh, another thing: the lawith nst part of the script works with a room with "normal" as music volume; of cours you can easily fix the script to fit any sound level ;)
Thanks for sharing your solution :)
Well that looks great! Would you mind posting a demo game of it?
I see better solution in a massive plugin.
What it should do, is play multiple tracks at the same time. Like, in separate channels.
But start playing both at very same moment.
Channels with adjustable volume (a crossfader between)
One track could play muted or quiet, when needed, main track quiets down and additional increases in volume... simple?
You would have to takeover functionality (with a DirectSound interface) to do it in a plugin.
I tried once really quickly, but failed; I have done next to no directX programming so I had a tough time starting.
I tried using the plugin API function AGS_EngineAudioHook, but it has been disabled according to CJ.
Edit: From the API
QuoteLPDIRECTSOUND GetDirectSound();
Returns the main IDirectSound interface that the engine is using. This command does not AddRef the pointer it returns, so you don't need to Release it.
This function returns NULL if sound is disabled, or if the player is using the WaveOut driver rather than the DirectSound one.
Added in version: 14
void DisableSound();
Disables AGS's sound system completely. Use this if you want your plugin to take over all audio functionality.
Added in version: 14
I'm not sure if you
need to DisableSound in order to use the DirectSound interface...
I hope khnum doesn't mind too much, but I've taken the liberty of modularizing his code here (http://americangirlscouts.org/bbc.com/yabb/index.php?topic=28933.0). He's mentioned in the module description and in the wiki entry...perhaps not in the documentation itself though...
No problem, happy to see my code's been useful :=