AudioChannel Null Pointer Exception

Started by nightmarer, Mon 23/01/2023 00:02:47

Previous topic - Next topic

nightmarer

Hello.

I am having a Null Pointer Exception with an Audio Channel set in one room, but it happens the second time I visit the room.

Code: ags
AudioChannel *acPropaganda;

function room_Load() {
 acPropaganda = aSpeech_close.Play();
 acPropaganda.SetRoomLocation(866, 252);
}

function room_Leave(){//Always exit from Station Out
 if(acPropaganda.IsPlaying) {
    acPropaganda.Stop();
 }
}

The SetRoomLocation line is the one which is returning the error, I tried using
Code: ags
function room_Load() {
 acPropaganda = aSpeech_close.Play();
 if (acPropaganda == null) 
  acPropaganda.SetRoomLocation(866, 252);
}
but then I'm having the Null Pointer Exception in the if.
I don't know what I'm doing wrong.

Crimson Wizard

#1
It should be:
Code: ags
if (acPropaganda != null) 

As you can use this pointer only if it's NOT null.

You should probably check the same in the room leave event as well:
Code: ags
if (acPropaganda != null && acPropaganda.IsPlaying) {
    acPropaganda.Stop();
 }

nightmarer

But why I need to use this "if" if I am playing that sound in the previous line?
Why is this pointer null, then?

Crimson Wizard

Quote from: nightmarer on Mon 23/01/2023 11:30:00But why I need to use this "if" if I am playing that sound in the previous line?
Why is this pointer null, then?

The Play() may return a null pointer if the sound failed to play for whatever reason:
- sound driver is not initialized;
- sound is stored in audio.vox, and audio.vox is missing;
- engine failed to start the playback, because of unsupported format or another problem;
- could not find a spare audio channel, and other running sounds have higher priority.

nightmarer

#4
Hello.
Quote from: Crimson Wizard on Mon 23/01/2023 11:45:17- sound driver is not initialized;
The rest of the room sounds are there being played.

Quote from: Crimson Wizard on Mon 23/01/2023 11:45:17- sound is stored in audio.vox, and audio.vox is missing;
- engine failed to start the playback, because of unsupported format or another problem;
The audio clip is being played the first time the character enters in the room.
Quote from: Crimson Wizard on Mon 23/01/2023 11:45:17- could not find a spare audio channel, and other running sounds have higher priority.
There are the same number of audio files played than the first time the character visits the room.

Crimson Wizard

#5
Is the question currently why do you need to check for null at all, or why Play returns null in that particular case?

I answered the first question, but I cannot answer the second without knowing more details about your game's audio, and particular circumstances.

nightmarer

#6
Quote from: Crimson Wizard on Mon 23/01/2023 23:29:58Is the question currently why do you need to check for null at all, or why Play returns null in that particular case?
I was checking for null just for debugging, as I was getting a NullPointerException I just wanted to know if the AudioChannel is null before playing it.

Quote from: Crimson Wizard on Mon 23/01/2023 23:29:58I answered the first question, but I cannot answer the second without knowing more details about your game's audio, and particular circumstances.

These are all the code lines related to this AudioChannel.
Code: ags
AudioChannel *acPropaganda;

function propagandaPlay() {
  if(acPropaganda == null) {
    Display("Is null");
    acPropaganda = aSpeech_close.Play();
  } 
  if(acPropaganda != null) {
    Display("Is not null");
    acPropaganda = aSpeech_close.Play();
    acPropaganda.SetRoomLocation(866, 252);
  }
  SetTimer(1, 1200);
}

function room_AfterFadeIn(){
    propagandaPlay();
}

function room_RepExec() {
  
  if(IsTimerExpired(1)) { //SPEECH
    if(!acPropaganda.IsPlaying) {
      propagandaPlay();
    }
    SetTimer(1, 1200);  
  }
}

function room_Leave(){
  if(acPropaganda.IsPlaying && acPropaganda != null) {
    acPropaganda.Stop();
  }
}

Do you need to know something else?

Khris

#7
The propagandaPlay function will call .Play() two times if the channel pointer is null.
Also, if the 2nd play command fails and the pointer ends up being null, you're calling SetRoomLocation on null, again causing a null pointer error.

I'd do this:

Code: ags
function propagandaPlay() {
  acPropaganda = aSpeech_close.Play();
  if (acPropaganda != null) acPropaganda.SetRoomLocation(866, 252);
  SetTimer(1, 1200);
}

Edit: fixed code

nightmarer

Quote from: Khris on Sat 28/01/2023 13:28:42The propagandaPlay function will call .Play() two times if the channel pointer is null.
Also, if the 2nd play command fails and the pointer ends up being null, you're calling SetRoomLocation on null, again causing a null pointer error.

I'd do this:

Code: ags
function propagandaPlay() {
  if(acPropaganda == null) acPropaganda = aSpeech_close.Play();
  if(acPropaganda != null) acPropaganda.SetRoomLocation(866, 252);
  SetTimer(1, 1200);
}
Thank you, but I'm afraid I have already tried that before. If I do that then the second time I visit the room the audio is not being played.

Crimson Wizard

#9
It should not make the first test for (acPropaganda == null) at all, since that does not matter, and it seems that sound must restart every time player enters the room. (It is stopped when player leaves the room).

The Khris's code will fail starting from the second time, because AudioChannel's pointer never gets null after being assigned for the first time.

Code: ags
function propagandaPlay() {
  acPropaganda = aSpeech_close.Play();
  if(acPropaganda != null) {
    acPropaganda.SetRoomLocation(866, 252);
  }
  SetTimer(1, 1200);
}



There's another problem in room_Leave, where you test for acPropaganda.IsPlaying before testing that acPropaganda is null. If acPropaganda were null at that moment, there will be a null pointer error when checking acPropaganda.IsPlaying. So the order of conditions should be different.
Besides that, this probably is not related to the problem, but I think you should also stop the timer when you leave the room in order to avoid potential conflicts with other rooms, which might use same timer ID:
Code: ags
function room_Leave() {
  if (acPropaganda != null && acPropaganda.IsPlaying) {
    acPropaganda.Stop();
  }
  SetTimer (1, 0);
}

Khris


nightmarer

Hello,

after the NullPointer error was solved and reviewing the error with Crimson Wizard, the problem of the sound not being played was caused by the audio channels assignation exceeded the requirements of 3.5.1 version.

Thank you very much for your help.

SMF spam blocked by CleanTalk