PDA

View Full Version : Game->SetMIDIVolume and other MIDI control functions in ZScript



Alucard
11-25-2017, 01:40 AM
One guy requested MIDI fadeout script (https://www.purezc.net/forums/index.php?showtopic=73186) and got an unpleasant response: tampering with MIDI playback on the fly is not possible in ZC at all, sans start/stop in abrupt manner. Perharps something like Game->SetMIDIVolume or similar function may resolve this audio-related issue.

ZoriaRPG
11-25-2017, 07:49 AM
One guy requested MIDI fadeout script (https://www.purezc.net/forums/index.php?showtopic=73186) and got an unpleasant response: tampering with MIDI playback on the fly is not possible in ZC at all, sans start/stop in abrupt manner. Perharps something like Game->SetMIDIVolume or similar function may resolve this audio-related issue.

I'd be more inclined to add Audio->Volume[5], as changing the volume for a MIDI stored in the quest file, while it is playing, would not affect its volume if it is playing at the time.

There are a number of things that I eventually want to do under Audio->, however, they are not trivial. I'll note, that the interfaces for each type of audio format, are entirely different, which makes creating some sort of streamlined function set to control them, quite difficult. Users also want loop control, pan control, and other things that are simply infuriating to add to ZScript.

ZoriaRPG
11-27-2017, 06:26 AM
One guy requested MIDI fadeout script (https://www.purezc.net/forums/index.php?showtopic=73186) and got an unpleasant response: tampering with MIDI playback on the fly is not possible in ZC at all, sans start/stop in abrupt manner. Perharps something like Game->SetMIDIVolume or similar function may resolve this audio-related issue.


I added Audio->Volume[4], and Audio->PanStyle. Both work, but I advise being considerate when using them.

Always store the user settings before; and restore the user volume after, you use them for effects:




int oldaudio = FadeMidi(120, 4);
//FadeOut
int FadeMIDI(int time, int ticks_per_decrement)
{
int oldvol = Volume[VOL_MIDI]; //Store the ore-fade setting.
for ( int q = 0; q < fade ; ++q )
{
if ( !(q%ticks_per_decrement) ) --(Audio->Volume[VOL_MIDI]);
if ( Audio->Volume[VOL_MIDI] < 1 ) return oldvol;
//Do not waste frames if we reach 0!
Waitframe();
}
return oldvol;
}

//FadeIn to the old volume
void FadeMIDI(int time, int ticks_per_decrement, int oldsetting)
{
int oldvol = Volume[VOL_MIDI]; //Store the ore-fade setting.
int q;
while( Audio->Volume[VOL_MIDI] < oldsetting )
{
if ( !(q%ticks_per_decrement) ) ++(Audio->Volume[VOL_MIDI]);
++q;
Waitframe();
}
}

Saffith
11-28-2017, 03:16 PM
I would say that giving scripts access to change the user's settings is pretty high on the list of things you should never do. If you want to give access to volume control, it should be something temporary that will automatically reset on quitting the quest. I'd also suggest that it be a 0..1 multiplier. That way, the same numbers will work consistently regardless of settings, and it will still make sense if the internal volume handling ever changes.

ZoriaRPG
11-29-2017, 03:30 AM
I would say that giving scripts access to change the user's settings is pretty high on the list of things you should never do. If you want to give access to volume control, it should be something temporary that will automatically reset on quitting the quest. I'd also suggest that it be a 0..1 multiplier. That way, the same numbers will work consistently regardless of settings, and it will still make sense if the internal volume handling ever changes.

I did add a mechanic to clear it on quest exit. The issue with the volume controls, is that I see no way around calling master_volume(digi,midi) and similar. Anything that modifies volume would ultimately write to the base variables. (e.g., There is no mid-level interface to adjust the volume of a stream as it is playing, because the audio API is awful.)

Instead, I cached the user settings, and restore them on exit, winning the game, and so forth. When a script changes any volume setting, the script instruction sets an FFCore flag for that setting, and stores the original volume. When any end-the-game event occurs, the stored values are restored for each component for which a flag was set.

Allegro does not have any mid-level access to volume settings. i wish that it did, so that I could use an offset instead, but the way that the system works, an offset would still write to midi_volume, digi_volume, emusic_volume, whatever.

I also set up an event that occurs if ZC is not in alpha/beta status, whereby opening the sound prefs dialogue automatically reverts the values to the user settings, so that the change is completely transparent, and so that the user can override it.

Gleeok
11-29-2017, 04:09 AM
Wait...what? I think I'm misreading this.. Did you actually give access to master volume settings to scripts? ...If so, that is a really bad idea and needs to be fixed. Guaranteed 100% that any scripts using those will not be supported in the future.

I use sound APIs that have channels built-in, and it works well, so I'd be inclined to create additional data for playing sounds that the sound engine can manage separate of user settings, although this is a lot of work and the allegro sound stuff is not fun. Saffith's suggestion sounds pretty good to me, I'd go with that

ZoriaRPG
11-29-2017, 10:29 PM
Fine, here:
https://github.com/ArmageddonGames/ZeldaClassic/commit/82bba643b2044f5bf1a67417b7df9fa3457e847f

This does not expose any of the allegro audio variables to the user. It's a function pair:
Audio->AdjustVolume(in percent)
Audio->AdjustSFXVolume(int percent)

Calling them should always set the volume to an absolute percentage of the user volume, so, AdjustVolume(100) would result in the volume remaining the same.

Volume changes revert to the user setting son quest exit, win game, etc..

If the audio API changes in the future, this binds it to only segregated music and sfx volume, rather than our present, three distinct types (at the function level). (AdjustVolume affects MIDI, DIGI, and Enhanced Music simultaneously.)

Is that sufficient?