본문 바로가기
개발(Development)/JS(자바스크립트)

Javascript: Audio 사운드 하나를 연속하여 반복/중복 재생하는 방법

by 카레유 2021. 6. 22.

Audio객체는

play()가 호출되어 재생이 시작 되면, 끝까지 재생이 완료되기 전에는 반복 호출하여 재생할 수 없다.

 

아래 코드는

for문으로 Audio객체.play()를 10회 반복 호출하지만, 브라우저에서 실행해보면 단 한번만 재생된다.

(크롬을 제외한 브라우저에서 실행해보시길. 크롬은 사용자의 액션이 없는 상태에서의 오디오 자동재생이 금지되어 있다)

<!DOCTYPE html>
<html lang="en">
    
<head>
</head>

<body>    
</body>

<script>

// Audio 객체 생성
const sound = new Audio();

// 리소스 설정
sound.src = "sound.mp3";

// 10회 반복 재생 시도: 실패!!! 단 1번만 재생됨
for(let i = 0; i < 10; i++){
    sound.play();
}

</script>
</html>

 

그러나 경우에 따라서는 동일한 음원 파일을 연달아 바로 재생해야할 때가 있다.

특히 게임 개발 중에는 미사일을 발사할 때마다 효과음이 중첩 재생되어야 한다.

 

필요할 때마다 매번 새로운 Audio 객체를 생성하여 재생하는 것도 방법이지만,

이 경우 Audio 리소스 로드에 시간이 걸려서 딜레이가 발생할 수 있다.

 

가장 좋은 방법은 미리 여러개의 Auido객체를 생성해두고, 배열에 담아두고 사용하는 게 아닐까 한다.

아래 코드는 10번 연달아 사운드가 반복 재생된다.

<!DOCTYPE html>
<html lang="en">
    
<head>
</head>

<body>    
</body>

<script>

// audio객체 여러개를 담아둘 배열
const arr_sound = [];

// audio객체 10개를 생성하여 배열에 담아둔다.
for(let i = 0; i < 10; i++){
    const sound = new Audio();
    sound.src = "sound.mp3";
    arr_sound.push(sound);
}

// 10번 연달아 audio객체를 재생한다: 성공!
for(let i = 0; i < arr_sound.length; i++){
    arr_sound[i].play();
}

</script>
</html>

 

버튼을 누를 때마다 사운드가 반복 재생되도록 구현하려면, 아래와 같이 코드를 작성하면 된다.

<!DOCTYPE html>
<html lang="en">
    
<head>
</head>

<body>
    <button id="btn_play">Play</button>
</body>

<script>

// Audio객체를 담아둘 배열
const arr_sound = [];

// 10개의 Audio객체를 배열에 담아둔다.
for(let i = 0; i < 10; i++){
    const sound = new Audio();
    sound.src = "sound.mp3";
    arr_sound.push(sound);
}

// 버튼을 누를 때마다, Audio객체를 재생
document.getElementById("btn_play").onclick = function(){
    for(let i = 0; i < arr_sound.length; i++){
        if(arr_sound[i].paused){ // 재생중이 아닌 Audio객체를 찾아서
            arr_sound[i].play(); // 1회만 재생하고
            break; // 반복문을 나간다.
        }
    }
}

</script>
</html>

 

크롬 브라우저의 경우 위 코드가 정상 작동하지 않을 수 있는데,

일부 크롬의 경우, 재생이 완료된 Audio객체를 재사용하려면 리소스를 다시 리로드 해주어야 하기 때문이다.

아래와 같이 간단한 예외 처리 코드를 추가해주면 된다.

<!DOCTYPE html>
<html lang="en">
    
<head>
</head>

<body>
    <button id="btn_play">Play</button>
</body>

<script>

// Audio객체를 담아둘 배열
const arr_sound = [];

// 10개의 Audio객체를 배열에 담아둔다.
for(let i = 0; i < 10; i++){
    const sound = new Audio();
    sound.src = "sound.mp3";

    // 크롬 예외 처리: audio 재생이 끝나면, 다시 로드해준다
    sound.addEventListener('ended', function(){
        if(window.chrome){this.load();}
        this.pause();
    })

    arr_sound.push(sound);
}

// 버튼을 누를 때마다, Audio객체를 재생
document.getElementById("btn_play").onclick = function(){
    for(let i = 0; i < arr_sound.length; i++){
        if(arr_sound[i].paused){ // 재생중이 아닌 Audio객체를 찾아서
            arr_sound[i].play(); // 1회만 재생하고
            break; // 반복문을 나간다.
        }
    }
}

</script>
</html>

 

 

단, 버튼을 빠르게 여러번 눌러서 모든 Audio가 play 중인 상태라면 약간의 텀이 발생할 수 밖에 없다.

 

이 경우,

1. 배열에 담는 audio객체의 갯수를 늘리면 되지만, 메모리를 많이 차지할 수 있다.

2. 신규 audio객체를 생성하여 play()를 호출해도 되지만, 파일크기가 크거나 인터넷 속도가 느린 경우엔 텀이 발생할 것이다.

 

상황에 맞게 알맞은 방법을 혼용하여 사용하면 될듯하다.

 

 

댓글