JavaScript / HTML5의 음향 효과


316

게임을 프로그래밍하기 위해 HTML5를 사용하고 있습니다. 내가 지금 겪었던 장애물은 음향 효과를 재생하는 방법입니다.

구체적인 요구 사항은 거의 없습니다.

  • 여러 사운드를 재생하고 믹스
  • 동일한 샘플을 여러 번 재생합니다.
  • 언제든 샘플의 재생을 중단
  • 바람직하게는 (저품질) 원시 PCM을 포함하는 WAV 파일을 재생하지만 물론 변환 할 수 있습니다.

첫 번째 방법은 HTML5 <audio>요소 를 사용하고 내 페이지에서 모든 사운드 효과를 정의하는 것이 었습니다. Firefox는 WAV 파일을 복숭아처럼 재생하지만 #play여러 번 호출 해도 실제로는 여러 번 재생되지 않습니다. HTML5 사양에 대한 나의 이해에서 <audio>요소는 재생 상태를 추적하므로 이유를 설명합니다.

내 생각은 오디오 요소를 복제하는 것이기 때문에 jQuery에 따라 다음과 같은 작은 JavaScript 라이브러리를 만들었습니다.

var Snd = {
  init: function() {
    $("audio").each(function() {
      var src = this.getAttribute('src');
      if (src.substring(0, 4) !== "snd/") { return; }
      // Cut out the basename (strip directory and extension)
      var name = src.substring(4, src.length - 4);
      // Create the helper function, which clones the audio object and plays it
      var Constructor = function() {};
      Constructor.prototype = this;
      Snd[name] = function() {
        var clone = new Constructor();
        clone.play();
        // Return the cloned element, so the caller can interrupt the sound effect
        return clone;
      };
    });
  }
};

이제 Snd.boom();Firebug 콘솔에서 할 수 있고을 재생할 snd/boom.wav수 있지만 여전히 동일한 샘플을 여러 번 재생할 수는 없습니다. 이 <audio>요소는 실제로 음향 효과를 재생하는 것이 아니라 스트리밍 기능에 가깝습니다.

HTML5와 JavaScript 만 사용하여 내가 빠졌을 수있는 영리한 방법이 있습니까?

또한 테스트 환경은 Ubuntu 9.10의 Firefox 3.5입니다. 내가 시도한 다른 브라우저-Opera, Midori, Chromium, Epiphany는 다양한 결과를 냈습니다. 일부는 아무것도하지 않으며 일부는 예외를 던집니다.


하! 또한 오래된 Macintosh 게임을 HTML5로 이식하고 있습니다. 어느 것을 복제하고 있는지 밝히시겠습니까?
유료

1
폭풍우의 프로젝트 아라시 프로젝트입니다.
Stéphan Kochen

"믹싱"사운드 란 무엇입니까?
Mads Skjern

2
끝냈어요? 우리가 볼 수 있습니까?
enyo

4
안타깝게도 여가 시간 프로젝트를 끝내지 않은 요령이 있습니다. :( 거기에 대한 자식의 repo는하지만 나는 몇 년 동안 그것을 손도 안 : github.com/stephank/arashi-js
스테판 Kochen

답변:


448

HTML5 Audio객체

당신은 <audio>요소 를 귀찮게 할 필요가 없습니다 . HTML 5를 사용하면 Audio객체에 직접 액세스 할 수 있습니다.

var snd = new Audio("file.wav"); // buffers automatically when created
snd.play();

현재 버전의 스펙에서 믹싱을 지원하지 않습니다.

동일한 사운드를 여러 번 재생하려면 Audio객체의 인스턴스를 여러 개 만듭니다 . snd.currentTime=0재생이 끝난 후에도 객체를 설정할 수 있습니다 .


JS 생성자는 대체 <source>요소를 지원하지 않으므로 사용해야합니다.

(new Audio()).canPlayType("audio/ogg; codecs=vorbis")

브라우저가 Ogg Vorbis를 지원하는지 테스트합니다.


게임 또는 음악 앱 (플레이어 이상)을 작성하는 경우 이제 대부분의 브라우저에서 지원되는 고급 Web Audio API 를 사용하려고 합니다 .


18
Audio객체는 자동 버퍼됩니다. 그것들은 Image객체와 유사하게 설계되었으므로 구식 이미지 사전로드 기술은 오디오에서도 작동합니다.
Kornel

5
이것은 iOS에서도 작동합니다. 당신이 있다고하지만주의 해야 할 사용자 작업의 어떤 종류를 사용하는 (예를 들어, 버튼 클릭이) 소리를 시작합니다. 당신은 snd.play()on window.load () 할 수 없습니다 .
Husky

1
<audio>태그가 더 제어 가능하기 때문에 여전히 태그를 사용하고 있습니다. 그러나 어쨌든 정보를 주셔서 감사합니다!
Derek 朕 會 功夫

2
<audio> html5 요소가 여러 소스를 허용하지 않기 때문에이 방법을 선호하므로 브라우저가 mp3를 지원하지 않으면 ogg / wav로 대체 할 수 있습니다. 동일한 결과를 얻으려면 자바 스크립트에 약간의 속임수가 필요합니다.
joelmdev

2
iOS 6에서는 자동 재생이 지원됩니다. window.load ()에서 간단한 snd.play ()를 사용하여 사운드를 시작할 수 있습니다.
Pietro Polsinelli 2013

36

W3C의 WebAudio API

2012 년 7 월 현재 WebAudio API 는 이제 Chrome에서 지원되고 Firefox에서 적어도 부분적으로 지원되며 버전 6부터 IOS에 추가 될 예정입니다.

기본 작업에 프로그래밍 방식으로 사용할 수있을 정도로 강력하지만 오디오 요소는 게임 등을 완벽하게 지원할 수 없습니다. 단일 미디어를 img와 유사한 페이지에 내장 할 수 있도록 설계되었습니다. 꼬리표. 게임에 오디오 태그를 사용하는 데 많은 문제가 있습니다.

  • 타이밍 슬립은 오디오 요소와 공통입니다
  • 사운드의 각 인스턴스에 오디오 요소가 필요합니다
  • 로드 이벤트는 아직 완전히 신뢰할 수는 없지만
  • 일반적인 볼륨 컨트롤, 페이딩 없음, 필터 / 효과 없음

WebAudio 시작하기 기사를 사용하여 WebAudio API를 시작했습니다. FieldRunners 웹 오디오 사례 연구 도 좋은 읽기입니다.


이 문제 (웹 오디오 API)에 대한 올바른 해결책에 초점을 맞추고으로 이것은 허용 하나보다 더 나은 해답이며, 그 이유 오디오 요소는 오히려 함께 오디오 요소와 나쁜 솔루션을 해킹하는 것보다, 좋은 솔루션 없습니다
Anomaly

29

howler.js

게임 제작의 경우 최상의 솔루션 중 하나는 howler.js 와 같이 웹용 코드를 작성할 때 직면하는 많은 문제를 해결하는 라이브러리를 사용하는 입니다. howler.js는 훌륭한 (그러나 저수준) 웹 오디오 API 를 사용하기 쉬운 프레임 워크로 추상화합니다 . 웹 오디오 API를 사용할 수없는 경우 HTML5 오디오 요소 로 폴백을 시도합니다 .

var sound = new Howl({
  urls: ['sound.mp3', 'sound.ogg']
}).play();
// it also provides calls for spatial/3d audio effects (most browsers)
sound.pos3d(0.1,0.3,0.5);

wad.js

또 다른 훌륭한 라이브러리 인 wad.js 는 음악 및 효과와 같은 신디사이저 오디오를 제작하는 데 특히 유용합니다. 예를 들면 다음과 같습니다.

var saw = new Wad({source : 'sawtooth'})
saw.play({
    volume  : 0.8,
    wait    : 0,     // Time in seconds between calling play() and actually triggering the note.
    loop    : false, // This overrides the value for loop on the constructor, if it was set. 
    pitch   : 'A4',  // A4 is 440 hertz.
    label   : 'A',   // A label that identifies this note.
    env     : {hold : 9001},
    panning : [1, -1, 10],
    filter  : {frequency : 900},
    delay   : {delayTime : .8}
})

게임 소리

Wad.js와 유사한 또 다른 라이브러리는 " Sound for Games "이며, 효과 제작에 더 중점을두고 있으며 비교적 뚜렷한 (그리고 더 간결한 느낌) API를 통해 유사한 기능을 제공합니다.

function shootSound() {
  soundEffect(
    1046.5,           //frequency
    0,                //attack
    0.3,              //decay
    "sawtooth",       //waveform
    1,                //Volume
    -0.8,             //pan
    0,                //wait before playing
    1200,             //pitch bend amount
    false,            //reverse bend
    0,                //random pitch range
    25,               //dissonance
    [0.2, 0.2, 2000], //echo array: [delay, feedback, filter]
    undefined         //reverb array: [duration, decay, reverse?]
  );
}

요약

하나의 사운드 파일을 재생하거나 자신 만의 HTML 기반 음악 편집기, 효과 생성기 또는 비디오 게임을 만들어야하는지 여부에 관계없이 이러한 라이브러리 각각을 살펴볼 가치가 있습니다.


게임 개발에 대해서는 언급 할 수 없지만 인터페이스에서 약간의 오디오 피드백을 위해 이것을 사용하고 있으며 절대적인 치료법으로 작동합니다. 빠르고 쉽고 간단합니다.
Rid Iculous

정말 좋은 프레임 워크, 모바일에서도 잘 작동합니다. 당신은 터치 스타트와 함께 그것을 트리거해야하지만 ... 일단 완료되면 즉시 작동합니다 :)
Philip

9

경우에 따라이 기능을 사용하여 HTML 5 오디오를 감지 할 수도 있습니다.

http://diveintohtml5.ep.io/everything.html

HTML 5 JS 감지 기능

function supportsAudio()
{
    var a = document.createElement('audio'); 
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
}

이것을 지적 해 주셔서 감사합니다. has.js에서이 방법을 배웠지 만, Firefox에서는 문제가 있고 has.js 소스 코드에 따르면 Opera에서도 문제가있는 것으로 보입니다. (ref : github.com/phiggins42/has.js/issues/48 github.com/phiggins42/has.js/blob/master/detect/audio.js#L19 )
Stéphan Kochen

5

동일한 사운드를 동시에 재생할 수있는 한 가지 방법이 있습니다. 프리 로더와 결합하면 모든 준비가 완료됩니다. 이것은 Firefox 17.0.1 이상에서 작동하지만 아직 다른 것으로 테스트하지 않았습니다.

// collection of sounds that are playing
var playing={};
// collection of sounds
var sounds={step:"knock.ogg",throw:"swing.ogg"};

// function that is used to play sounds
function player(x)
{
    var a,b;
    b=new Date();
    a=x+b.getTime();
    playing[a]=new Audio(sounds[x]);
    // with this we prevent playing-object from becoming a memory-monster:
    playing[a].onended=function(){delete playing[a]};
    playing[a].play();
}

이것을 키보드 키에 묶고 즐기십시오.

player("step");

아니요. 개별 사운드 재생마다 새로운 객체를 만드는 것이 전혀 해결책이라고 생각하지 않습니다. 빠르고 더러운 해결 방법이지만 더 잘 수행 할 수 있습니다.
Pawel

@Pawel 사실, 이것이 사운드를 재생하는 주요 방법으로 사용되어서는 안되지만, 내가 아는 한, 예제의 원칙은 동일한 사운드를 동시에 두 번 이상 또는 OP가 표현한 유일한 방법입니다. "겹치는 재생". (브라우저 플러그인이 필요하지 않습니다.) 현재 프로젝트의 실제 구현은 내가 게시 한 예제 코드보다 훨씬 정교합니다.
F-3000

4

원하는 것이 멀티 채널 사운드입니다. 실제로 16 비트 게임과 같이 4 개의 채널이 있다고 가정하고 HTML5 오디오 기능을 사용하는 데 어려움을 겪지 않았지만 4 개의 <audio> 요소 만 있으면되고 사용되는주기는 아닙니다. 다음 음향 효과를 재생하려면? 당신은 그것을 시도 했습니까? 무슨 일이야? 작동하는 경우 : 더 많은 사운드를 동시에 재생하려면 <audio> 요소를 더 추가하십시오.

http://flash-mp3-player.net/ 의 작은 Flash 객체를 사용하여 HTML5 <audio> 요소 없이이 작업을 수행했습니다 . 음악 퀴즈 ( http://webdeavour.appspot.com/ )를 작성했습니다. 사용자가 질문 버튼을 클릭했을 때 음악 클립을 재생하는 데 사용했습니다. 처음에는 질문 당 한 명의 플레이어가 있었고 서로의 상단에서 재생할 수 있었기 때문에 다른 음악 클립을 가리키는 한 명의 플레이어만이되도록 변경했습니다.


& lt; audio & gt; 요소를 채널로 한 페이지에 두 요소를 넣으면 동시에 재생할 있습니다. 원래 코드에서 두 개의 샘플을 재생해도 효과가 있기 때문에 내가하고있는 복제가 실제로 예상대로 작동하지 않는 것처럼 보입니다. 동일한 샘플의 두 배가 아닙니다. 나는 이것을 좀 더 실험해야하고 결과를 다시 얻을 것이다!
Stéphan Kochen

예, 복제본이 아니라 복제본이라고 불리는 미묘한 이유가있을 수 있습니다. 아마도 클론은 원본과 무언가를 공유하고 있기 때문에 둘 다 동시에 재생되지 않을 수 있습니다.
Lee Kowalkowski

참고로 적어도 Firefox에서는 동일한 <audio> 요소를 다시 사용할 수 없습니다. 'src'속성을 설정할 수 있지만 실제로 다른 샘플을로드하지는 않습니다.
Stéphan Kochen

4

jai (-> mirror ) (javascript audio interface) 사이트를 살펴보십시오 . 소스를 살펴보면 play()반복해서 호출하는 것처럼 보이며 라이브러리는 HTML5 기반 게임에 사용하기에 적합 할 수 있다고 언급합니다.

자바 스크립트 게임을 만들거나 배경 음악을 통해 음성으로 말하기 위해 여러 오디오 이벤트를 동시에 실행할 수 있습니다.


3

동일한 샘플을 여러 번 재생하려면 다음과 같은 작업을 수행 할 수 없습니다.

e.pause(); // Perhaps optional
e.currentTime = 0;
e.play();

( e오디오 요소입니다)

어쩌면 나는 당신의 문제를 완전히 이해하지 못했을 것입니다. 사운드 효과가 동시에 여러 번 재생되기를 원하십니까? 그렇다면 이것은 완전히 잘못되었습니다.


맞습니다. 같은 샘플을 동시에 여러 번 재생해야합니다.
Stéphan Kochen

예, 동일한 인스턴스를 여러 번 재생하지만이 답변을 보는 사람들에게는 OP라는 단어로 "중첩 재생"이 발생하지 않습니다.
Patrick Roberts

3

여기 아이디어가 있습니다. 특정 클래스의 사운드에 대한 모든 오디오를 하나의 개별 오디오 요소에로드합니다. src 데이터는 인접한 오디오 파일의 모든 샘플입니다 (아마도 약간의 시간을두고 샘플을 포착하고 잘라낼 수 있도록 사이에 약간의 침묵이 필요함) 다음 샘플로의 출혈 위험). 그런 다음 샘플을 찾아 필요할 때 재생하십시오.

재생하기 위해 이들 중 하나 이상이 필요한 경우 동일한 src로 추가 오디오 요소를 만들어 캐시되도록 할 수 있습니다. 이제 여러 개의 "트랙"이 효과적으로 만들어졌습니다. Round Robin 등 선호하는 리소스 할당 체계로 트랙 그룹을 활용할 수 있습니다.

또한 해당 리소스를 사용할 수있게되거나 현재 재생중인 샘플을 잘라낼 때 재생할 큐에 사운드 큐잉과 같은 다른 옵션을 지정할 수도 있습니다.



2

개발에 도움이되는 라이브러리 인 SoundJS를 사용하는 것이 좋습니다 . SoundJS가 웹 오디오, html 오디오 또는 플래시 오디오를 적절히 선택하여 어디에서나 작동하는 단일 코드 기반을 작성할 수 있습니다.

원하는 모든 작업을 수행 할 수 있습니다.

  • 여러 사운드를 재생하고 믹스
  • 동일한 샘플을 여러 번 재생하며 겹치는 재생
  • 언제든 샘플을 중단 재생
  • 포함 된 WAV 파일 재생 (브라우저 지원에 따라 다름)

희망이 도움이됩니다.


그 라이브러리는 굉장합니다. 저는 정말로 sfx 생성기를 파고 있습니다. 관심있는 사람
RozzA

1

단일 <audio>요소로 멀티 샷 재생을 할 수 없습니다 . 이를 위해 여러 요소를 사용해야합니다.


1

뮤직 박스 카드 생성기를 프로그래밍하는 동안이 문제가 발생했습니다. 다른 라이브러리로 시작했지만 항상 결함이있었습니다. 일반적인 오디오 구현의 지연은 나쁘고 여러 번 재생되지 않았습니다.

http://lowlag.alienbill.com/http://www.schillmania.com/projects/soundmanager2/

http://musicbox.grit.it/ 에서 구현을 확인할 수 있습니다 .

멀티 브라우저 재생을 위해 wav + ogg 파일을 생성했습니다. 이 뮤직 박스 플레이어는 ipad, iphone, Nexus, mac, pc에서 반응 형으로 작동합니다.


멋진 뮤직 박스 앱입니다! 자식 저장소가 있습니까? 우리 아이들과 함께 사용할 수도 있습니다!
icarito 17

0

나는 이것이 완전한 해킹이라는 것을 알고 있지만 얼마 전에 github에 넣은이 샘플 오픈 소스 오디오 라이브러리를 추가해야한다고 생각했습니다 ...

https://github.com/run-time/jThump

아래 링크를 클릭 한 후 홈 행 키를 입력하여 블루스 리프를 재생하십시오 (여러 키를 동시에 입력하는 등).

jThump 라이브러리를 사용한 샘플 >> http://davealger.com/apps/jthump/

기본적으로 <iframe>onReady () 사운드를 재생하는 페이지를로드하는 보이지 않는 요소를 만들어 작동합니다 .

이것은 확실히 이상적이지 않습니다 않지만 독창성에 기초 하여이 솔루션을 +1 할 수 있습니다 (그리고 그것이 오픈 소스이며 내가 시도한 모든 브라우저에서 작동한다는 사실). 다른 사람이 적어도 몇 가지 아이디어를 검색 할 수 있기를 바랍니다.

:)


왜 누군가가 이것을 투표하지 않았습니까? 나에게 실용적인 옵션 인 것 같습니다.
jtrick

그것은 꽤 해키 솔루션이지만이 라이브러리를 사용하여 샘플 html 5 캔버스 게임을 만들었으므로 덜 작동 할 수 있습니다 ...이 라이브러리를 사용하는 게임은 여기입니다 -beepbox.net
DaveAlger

0

선택한 답변은 IE를 제외한 모든 곳에서 작동합니다. 크로스 브라우저 = http://www.andy-howard.com/how-to-play-sounds-cross-browser-include-ie/index.html에서 작동시키는 방법에 대한 자습서를 작성했습니다 .

내가 쓴 기능은 다음과 같습니다.

function playSomeSounds(soundPath)
 {

 var trident = !!navigator.userAgent.match(/Trident\/7.0/);
 var net = !!navigator.userAgent.match(/.NET4.0E/);
 var IE11 = trident && net
 var IEold = ( navigator.userAgent.match(/MSIE/i) ? true : false );
 if(IE11 || IEold){
 document.all.sound.src = soundPath;
 }
 else
 {
 var snd = new Audio(soundPath); // buffers automatically when created
 snd.play();
 }
 };

또한 HTML 페이지에 다음 태그를 추가해야합니다.

<bgsound id="sound">

마지막으로 함수를 호출하고 간단히 경로를 전달할 수 있습니다.

playSomeSounds("sounds/welcome.wav");

0

항상 AudioContext지원이 제한되어 있지만 웹 오디오 API 작업 초안 의 일부입니다 . 앞으로 무언가를 출시 할 계획이라면 그만한 가치가있을 것입니다. 그리고 크롬과 파이어 폭스만을 프로그래밍한다면 황금색입니다.


0

var AudioContextFunc = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContextFunc();
var player=new WebAudioFontPlayer();
var instrumVox,instrumApplause;
var drumClap,drumLowTom,drumHighTom,drumSnare,drumKick,drumCrash;
loadDrum(21,function(s){drumClap=s;});
loadDrum(30,function(s){drumLowTom=s;});
loadDrum(50,function(s){drumHighTom=s;});
loadDrum(15,function(s){drumSnare=s;});
loadDrum(5,function(s){drumKick=s;});
loadDrum(70,function(s){drumCrash=s;});
loadInstrument(594,function(s){instrumVox=s;});
loadInstrument(1367,function(s){instrumApplause=s;});
function loadDrum(n,callback){
  var info=player.loader.drumInfo(n);
  player.loader.startLoad(audioContext, info.url, info.variable);
  player.loader.waitLoad(function () {callback(window[info.variable])});
}
function loadInstrument(n,callback){
  var info=player.loader.instrumentInfo(n);
  player.loader.startLoad(audioContext, info.url, info.variable);
  player.loader.waitLoad(function () {callback(window[info.variable])});
}
function uhoh(){
  var when=audioContext.currentTime;
  var b=0.1;
  player.queueWaveTable(audioContext, audioContext.destination, instrumVox, when+b*0, 60, b*1);
  player.queueWaveTable(audioContext, audioContext.destination, instrumVox, when+b*3, 56, b*4);
}
function applause(){
  player.queueWaveTable(audioContext, audioContext.destination, instrumApplause, audioContext.currentTime, 54, 3);
}
function badumtss(){
  var when=audioContext.currentTime;
  var b=0.11;
  player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*0, drumSnare.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumLowTom, when+b*0, drumLowTom.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*1, drumSnare.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumHighTom, when+b*1, drumHighTom.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*3, drumSnare.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumKick, when+b*3, drumKick.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumCrash, when+b*3, drumCrash.zones[0].keyRangeLow, 3.5);
}
<script src='https://surikov.github.io/webaudiofont/npm/dist/WebAudioFontPlayer.js'></script>
<button onclick='badumtss();'>badumtss</button>
<button onclick='uhoh();'>uhoh</button>
<button onclick='applause();'>applause</button>
<br/><a href='https://github.com/surikov/webaudiofont'>More sounds</a>


0

Web Audio API는이 작업에 적합한 도구입니다. 사운드 파일을로드하고 재생하는 데 약간의 작업이 있습니다. 다행히도 작업을 단순화하는 라이브러리가 많이 있습니다. 소리에 관심을 가지고 musquito 라는 라이브러리를 만들었습니다. .

현재는 페이딩 사운드 효과 만 지원하며 3D 공간화와 같은 다른 작업을하고 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.