Anna F Anna F - 1 year ago 139
TypeScript Question

Play 2 sounds one after another in Angular2

I have two sounds

say_1() { //music
this.audio.src = './sound1.wav';
this.audio.load();
// auto-start
this.audio.play();
}
say_2() { //speech
this.audio.src = './sound2.wav';
this.audio.load();
// auto-start
this.audio.play();
}


And I would like to make method
play_all();
which plays one sound after another

play_all () {
this.say_1();
this.say_2();
}


So, I would like to play as first my music and after that the speech,
but in my method it plays just second wav and I guess it's because I have this method

ngOnDestroy() {
// destroy audio here
if (this.audio) {
this.audio.pause();
this.audio = null;
}
}


I need this method, because if I leave page ( go to the next page via router ) music from previous page still plays.

How could I modify my method, so it would play both sound one after another?

Answer Source

The reason is that the audio is being played asynchronously. It means this play() method does not wait until the playback has finished.

In order to play these sounds one after another you have to start playing your second file when ended event happened.

The most naive solution could look like this:

 say_1() { //music
    this.audio.src = './sound1.wav'; 

    // whenever playback ends call the next function
    this.audio.onended = () => {
        this.audio.onended = null;
        this.say_2();
    }

    this.audio.load();
    this.audio.play();
 }

 say_2() { //speech
    this.audio.src = './sound2.wav';
    this.audio.load();
    this.audio.play();
 }

Then instead of playAll() you could just invoke the say_1() method.

You could also extract this into a AudioPlayerService somehow like this:

@Injectable()
export class AudioPlayerService {

    playbackEndedSource = new Subject<string>();
    playbackEnded$ = this.playbackEndedSource.asObservable();

    constructor() {
        // this.audio initialization
        this.audio.addEventListener('ended', () => this.playbackEndedSource.next());

    }

    play(path: string): void {
        this.audio.src = path;
        this.audio.load();
        this.audio.play();
    }

}

Then you could do it like this

export class AppComponent {
    constructor(private player: AudioPlayerService) {}

    playAll() {

        const subscription = player.playbackEnded$
            .subscribe(() => {
                player.play('audio2.wav');
                // to prevent it from playing over and over again
                subscription.unsubscribe();
            });
        player.play('audio1.wav');

    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download