Jibble

Author Topic: Counting AudioChannels manually  (Read 2322 times)

Monsieur OUXX

  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
Counting AudioChannels manually
« on: 29 Nov 2016, 12:00 »
A thing is puzzling me : how does the number of channels vary?
- In AGS 3.4.x+ : Is System.AudioChannelCount constant? Even when clips are playing?
- In older AGS versions: what would be a good way of counting the channels?

I've tried as follows:
- All my AudioTypes have "MaxChannels"=0 (unlimited channels), except one. That one has MaxChannels=2.
- Then I run this function, using a clip that has an "unlimited channels" AudioType with MaxChannels=0.
Code: Adventure Game Studio
  1. //This function only makes sense before System.AudioChannelCount was introduced -- AGS 3.3.x
  2.  
  3. //MAX_AUDIOCHANNELS : any value higher than the expected result (probbaly should be 7 or 8)
  4. #define MAX_AUDIOCHANNELS 9
  5. void CountAudioChannels(AudioClip* testClip)
  6. {
  7.     AudioChannel* audioChannels[MAX_AUDIOCHANNELS];
  8.  
  9.     //We'll count the audiochannels by playing priority 1 sounds until one of them uses a previously-used channel
  10.     //IMPORTANT: this clip's Audiotype must have a setting that allows to use an unlimited number of channels (max channel = 0)
  11.     AudioChannel* firstChannel = testClip.Play(eAudioPriorityVeryHigh, eOnce);
  12.     audioChannels[0]= firstChannel;
  13.     AudioChannel* otherChannel = testClip.Play(eAudioPriorityVeryHigh, eOnce);
  14.  
  15.     nbAudioChannels = 1;
  16.     while (otherChannel != firstChannel)
  17.     {
  18.         audioChannels[nbAudioChannels] = otherChannel;
  19.         nbAudioChannels++;
  20.         otherChannel = testClip.Play(eAudioPriorityVeryHigh, eOnce);
  21.     }
  22.     #endif
  23.  
  24.     Display("Counted %d AudioChannels.", nbAudioChannels);
  25. }
  26.  
  27.  

the result is 5. When al my AudioTypes have MaxChannels=0, the same function returns 7. So I infere that 5 is probably the result of 7-2.
So does that mean that the AudioType that has MaxChannels=2 reserves the channels? I thought that would mean it can use 2 channels at most.
 

Snarky

  • Global Moderator
  • Private Insultant
    • I can help with proof reading
    • I can help with translating
Re: Counting AudioChannels manually
« Reply #1 on: 29 Nov 2016, 12:07 »
So does that mean that the AudioType that has MaxChannels=2 reserves the channels?

Yes.

Monsieur OUXX

  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
Re: Counting AudioChannels manually
« Reply #2 on: 29 Nov 2016, 12:13 »
So does that mean that the AudioType that has MaxChannels=2 reserves the channels?

Yes.
Damn. Thanks.
At the moment I'm trying to find tricks to reduce the waste of channels as much as possible.
 

Re: Counting AudioChannels manually
« Reply #3 on: 29 Nov 2016, 12:17 »
I am not so sure about them reserving channels, I kept thinking this is the number of most used per type at any given moment. This might need clarification.

Quote
In AGS 3.4.x+ : Is System.AudioChannelCount constant? Even when clips are playing?
As I was explaining before, the number of audio channels never changes. And it currently should be 8 always, since there is no way to configure their count.
They are like slots. Or available chairs in the room where you sit people (clips). Their number does not change when people sit down or stand up.


Quote
In older AGS versions: what would be a good way of counting the channels?
Quote
//This function only makes sense before System.AudioChannelCount was introduced -- AGS 3.3.x
No, this information is incorrect, channels and respective properties exist since AGS 3.2.0.

Quote from Changes.txt:
Quote
VERSION 3.2, June 2010
 - Rewrote audio system. The old number-based sound and music are gone, replaced with
   new named audio clips. Added AudioClip.*, AudioChannel.*, Game.IsAudioPlaying,
   Game.SetAudioTypeVolume, Game.StopAudio, System.AudioChannels, System.AudioChannelCount,
   System.Volume, ViewFrame.LinkedAudio script commands.

In earlier versions there were only 3 or 4 fixed channels for every sound type (speech, music, sound, and possibly separate one for ambient sound), and users had no control over them.
« Last Edit: 29 Nov 2016, 12:28 by Crimson Wizard »

Snarky

  • Global Moderator
  • Private Insultant
    • I can help with proof reading
    • I can help with translating
Re: Counting AudioChannels manually
« Reply #4 on: 29 Nov 2016, 12:31 »
I am not so sure about them reserving channels, I kept thinking this is the number of most used per type at any given moment. This might need clarification.

That would be better, but it's not how the system works (at least as of 3.3.3).

-Every AudioType reserves at least 1 channel (even if MaxChannels is set to 0) (Wrong)
-If MaxChannels is set to some other number, the AudioType reserves that many channels

Method of testing:

With default game, three audio types (Ambient, Music, Sound). The game tries to play first one music track, and then another at the same time, without using Ambient or Sound at all.

1. Set MaxChannels to 0 for Music and Sound, 1 for Ambient. Result: Both music tracks play, as expected.
2. Set MaxChannels to 0 for Music and Sound, 7 for Ambient. Result: No music, because the setup tries to assign 9 channels, which doesn't work. (actually because 7 for ambient + 1 for speech leaves none for any other type of audio)
3. Set MaxChannels to 0 for Music and Sound, 6 for Ambient. Result: The first music track plays. On trying to play the second, the first one stops.

The third test demonstrates that having assigned 6 channels to Ambient (and implicitly 1 for Sound one reserved for speech), there is only one audio channel left to play music.
« Last Edit: 30 Nov 2016, 15:10 by Snarky »

Re: Counting AudioChannels manually
« Reply #5 on: 29 Nov 2016, 20:55 »
Heh, perhaps we should just rename MaxChannels to ReservedChannels, we always end up realizing that it reserves channels, but the next time it comes up no one remembers and everyone is in doubt again.
It's a vicious cycle. :-D

- Alan

Monsieur OUXX

  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
Re: Counting AudioChannels manually
« Reply #6 on: 29 Nov 2016, 22:55 »
I've written a module that counts and lists almost everything that's possible to count (AudioTypes, AudioChannels, AudioClips, reserved channels, etc.), even in AGS 3.3.x.
Retrospectively, I agree that the channels are not so hard to understand, but they're confusing at first. Writing this module helped me a great deal to pay attention to aspects of channel management that seem straightforward if you don't pay enough attention but are actually quite subtle.

I'll publish it in the next few days. There's a graphical interface to it to visualize what's going on, and everything is named instead of using numbers. It should help beginners a lot.

« Last Edit: 29 Nov 2016, 23:09 by Monsieur OUXX »
 

Re: Counting AudioChannels manually
« Reply #7 on: 29 Nov 2016, 23:17 »
-Every AudioType reserves at least 1 channel (even if MaxChannels is set to 0)
-If MaxChannels is set to some other number, the AudioType reserves that many channels
Heh, perhaps we should just rename MaxChannels to ReservedChannels, we always end up realizing that it reserves channels,

Then I guess they work in both ways: as reserving AND as limiting. That is if you put 1 channel for music, every next music will replace that one, even if you have free channels.
In other words that's rather something like "designated channels".

If channels = 0, then that audio will take any available non-designated channel.
« Last Edit: 29 Nov 2016, 23:20 by Crimson Wizard »

Snarky

  • Global Moderator
  • Private Insultant
    • I can help with proof reading
    • I can help with translating
Re: Counting AudioChannels manually
« Reply #8 on: 30 Nov 2016, 01:11 »
The system makes sense on its own terms, but could be explained a lot better in the manual.

As far as I'm concerned, the big gotcha is that even if you set its MaxChannels to 0, each AudioType still reserves 1 channel for its exclusive use. (Edit: Wrong)
« Last Edit: 30 Nov 2016, 15:06 by Snarky »

Re: Counting AudioChannels manually
« Reply #9 on: 30 Nov 2016, 08:45 »
As far as I'm concerned, the big gotcha is that even if you set its MaxChannels to 0, each AudioType still reserves 1 channel for its exclusive use.
I this is true for custom types? I think there are 3 built-in types that reserve channels  unconditionally, which is done for backwards-compatibility (functions like PlayMusic).

Monsieur OUXX

  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
Re: Counting AudioChannels manually
« Reply #10 on: 30 Nov 2016, 13:24 »
even if you set its MaxChannels to 0, each AudioType still reserves 1 channel for its exclusive use.

I haven't observed that with my custom type.
I'll need to try that with built-in types while some AudioClips (that use the built-in types) play .

« Last Edit: 30 Nov 2016, 13:26 by Monsieur OUXX »
 

Snarky

  • Global Moderator
  • Private Insultant
    • I can help with proof reading
    • I can help with translating
Re: Counting AudioChannels manually
« Reply #11 on: 30 Nov 2016, 15:05 »
I this is true for custom types? I think there are 3 built-in types that reserve channels  unconditionally, which is done for backwards-compatibility (functions like PlayMusic).

It's not true at all, I was wrong.

I was inferring the reservation of an AudioChannel per AudioType from the fact that when setting MaxChannels to 6+0+0, one of the "unlimited" types was only able to use one AudioChannel. However, upon further testing it seems like there are actually only 7 AudioChannels available for use by the AudioTypes, since one is always reserved for speech, so my logic was off. (If there is a way to free up this channel, I couldn't find it. It's off-limits even if you set Speech.VoiceMode=eSpeechTextOnly)

In fact, AudioTypes for which MaxChannels is set to 0 do not reserve any AudioChannels, at least not under any circumstances I could find.

Here's a snippet of code to examine the audio channel status (it uses a debug GUI with a label lblStatus), which goes in repeatedly_execute_always():

Code: Adventure Game Studio
  1. // Displays the status of the audio channels in format '[Channel#]: [AudioType] - [ClipName/SpeakingCharacter]'
  2.    String status="";
  3.    int i=0;
  4.    while(i<System.AudioChannelCount)
  5.    {
  6.       String clipType="NONE";
  7.       String clipName="";
  8.       AudioChannel* channel = System.AudioChannels[i];
  9.       if(channel != null && channel.IsPlaying)
  10.       {
  11.          AudioClip* clip = channel.PlayingClip;
  12.          if(clip == null) // If the channel is playing but the clip is null, it means it's playing speech
  13.          {
  14.             clipType="Speech";
  15.             // Figure out which character is speaking
  16.             int j=0;
  17.             while(j<Game.CharacterCount)
  18.             {
  19.                if(character[j].Speaking)
  20.                   clipName=character[j].Name;
  21.                j++;
  22.             }
  23.          }
  24.          else
  25.          {
  26.             if(clip.Type == eAudioTypeAmbientSound)
  27.                clipType="Ambient";
  28.             else if(clip.Type == eAudioTypeSound)
  29.                clipType="Sound";
  30.             else if(clip.Type == eAudioTypeMusic)
  31.                clipType="Music";
  32.             else if(clip.Type == eAudioTypeCustom)  // This is a custom audio type I created for testing
  33.                clipType="Custom";
  34.             else clipType = "Unknown";
  35.            
  36.             // There's no way to get the name of a clip, so if we need to identify it specifically, we have to special-case the check
  37.             if(clip==aLostCraftHowl) clipName="Aircraft";
  38.             else if(clip==aElectricNoise) clipName="Electric";
  39.             else if(clip==aRadioNoise) clipName="Radio";
  40.             else if(clip==aTone_01) clipName="Music1";
  41.             else if(clip==aTone_02) clipName="Music2";
  42.             else clipName="Unknown";
  43.          }
  44.       }
  45.       String line = String.Format("%d: %s - %s[",channel.ID, clipType, clipName);
  46.       status = status.Append(line);
  47.       i++;
  48.    }
  49.    lblStatus.Text=status;
« Last Edit: 30 Nov 2016, 15:18 by Snarky »

Snarky

  • Global Moderator
  • Private Insultant
    • I can help with proof reading
    • I can help with translating
Re: Counting AudioChannels manually
« Reply #12 on: 30 Nov 2016, 16:24 »
With this debug code, I was able to spot what I think must be a bug in the AGS sound system: If you try to play a clip when you've run out of AudioChannels for that AudioType, so that it has to preempt a currently playing clip, it actually stops all copies of that clip (at least sometimes). This explains some weird behavior that a number of people have noticed but not been able to fully describe in the past (including bugs with the applause system in the AGS Awards Ceremony, and possibly the problems Monsieur OUXX was having that started this whole thing in the first place).

I'm using the two-click game template default game, and I've added this code in Room 1:

Code: Adventure Game Studio
  1. #define MAXCHANNELS_SOUND 5    // This matches the Sound AudioType setup
  2. int soundTracks=0;
  3.  
  4. function hTeeVee_Interact()
  5. {
  6.    soundTracks++;
  7.    if(soundTracks%2==0)
  8.       aBirthday.Play(eAudioPriorityHigh, eRepeat);    // AudioType Sound
  9.    else
  10.       aLostCraftHowl.Play(eAudioPriorityHigh, eRepeat); // AudioType Sound
  11. }
  12.  
  13. function hTeeVee_Look()
  14. {
  15.    aLostCraftHowl.Stop();
  16.    aBirthday.Stop();
  17.    soundTracks=0;
  18. }

So each time I click on the TV, it starts playing another copy of one of the sound clips. The first five times, it correctly alternates between the two clips. But then on the sixth time (i.e. once we've run out of channels), things break. Usually, it will stop all the channels playing aLostCraftHowl (so you end up with three channels playing aBirthday and two playing nothing). Sometimes it will do the right thing (stop only one of the channels), in particular after the first time: if you keep playing more clips, it won't (ever?) happen again even once you run out of the channels that were freed up by the clips that stopped playing, but if you stop all the clips and start over, it does recur.

I've tested a few variations. Most notably, the behavior differs if you switch the audio clips around, which indicates it has something to do with the clip itself. As far as I can tell, it has to do with the clip being preempted (not the one you're trying to play): in this case, preempting the clip aLostCraftHowl tends to stop all copies of the clip, while preempting aBirthday is (usually?) OK.

It doesn't matter whether the channel limit is set explicitly by MaxChannels or implicitly by how many are left over from other audio types. It doesn't matter if the clips are playing on eRepeat or eOnce.

Monsieur OUXX

  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
Re: Counting AudioChannels manually
« Reply #13 on: 30 Nov 2016, 16:33 »
- I'm relieved to read that there isn't an implicitly-reserved channel for the built-in AudioTypes that have MaxChannels=0. That would have been one more irregularty to manage :-D
- I don't think the potential bug you've observed is what made me start my investigations; I was just too stupid to spot that the "pointers" to AudioChannels are constant even if the channel starts playing something new.
- However, yes this is potentially a bug -- except if CW manages to shade some light onto this behaviour.

 

Snarky

  • Global Moderator
  • Private Insultant
    • I can help with proof reading
    • I can help with translating
Re: Counting AudioChannels manually
« Reply #14 on: 30 Nov 2016, 16:40 »
I thought of some further testing to do, and as far as I can tell, it's actually a problem not with running out of channels as such, but with stopping/preempting channels playing certain clips. In this case, it seems like all copies of the clip aLostCraftHowl (which is a WAV file) will usually stop playing if you stop or preempt any channel that is playing the clip (even if you preempt it with itself).

I still haven't figured out the conditions under which it doesn't break.

Monsieur OUXX

  • Mittens Half Initiate
    • I can help with proof reading
    • I can help with translating
    • I can help with voice acting
Re: Counting AudioChannels manually
« Reply #15 on: 01 Dec 2016, 12:19 »
OK; good to know thanks

EDIT:
it's actually a problem with stopping/preempting channels playing certain clips. In this case, it seems like all copies of the clip stop playing if you stop or preempt any channel that is playing the clip (even if you preempt it with itself).
Could it be that the engine internally calls its internal implementation of AudioClip::Stop, which (by design) stops all instances of the playing AudioClip?
 
« Last Edit: 01 Dec 2016, 12:53 by Monsieur OUXX »