소개

HTML과 자바스크립트를 이용해 아래와 같이 숫자(Transpose)를 조절하면 서버 상에 있는 오디오 음원의 음정(pitch, 음높이)이 높아지거나 낮아지게 할 수 있습니다.

웹 페이지에서 다른 음높이의 오디오 음원을 재생하고 싶을 때 사용합니다.

장점
  • 외부 라이브러리를 사용하지 않습니다.
단점
  • 음정을 높이면 속도도 같이 조절됩니다. (음정과 속도가 연동됩니다.)
    • playbackRate를 조절하여 속도를 낮춰보려 했으나 속도를 낮추면 음정도 같이 낮아집니다.

 

코드

<button id="play1">예제 1 플레이</button> Transpose: <input id="stepper1" type="number" value="0">
var context = new AudioContext();
var source = context.createBufferSource();
var buffer1 = null;
var isPlaying1 = false;

// mp3 파일 받아오기
var request = new XMLHttpRequest();
request.open( 'GET', 'http://somewhere.con/musicsource.mp3', true );
request.responseType = 'arraybuffer';
request.onload = function() {
    context.decodeAudioData(request.response, function(buffer) {
        console.log(buffer);
    buffer1 = buffer;
    }, function(err) { console.log(err); });
}
request.send();

// 이벤트 지정
document.querySelector("#stepper1").addEventListener("change", function() {
    if(isPlaying1) {
        source.stop();
        start1();
    }
});

document.querySelector("#play1").addEventListener("click", function() {
    if(isPlaying1) {
        source.stop();
    } else {
        start1();
    }
    isPlaying1 = !isPlaying1
});

// source를 리셋하고, 파일을 재생
function start1() {
    source = context.createBufferSource();
    source.buffer = buffer1;
    source.connect(context.destination);
    var transpose = parseInt(document.querySelector("#stepper1").value);
    source.detune.value = transpose.value * 100; 
    if(transpose !== 0) {
        console.log(source.playbackRate, Math.pow(2, transpose / 12))
    }
    source.start(0);
}

오디오, 음정 오디오 음정 음원 음높이 피치 센트 세미톤 반음 자바스크립트 자스 mp3 오디오오디오를  외동 오디오를 오디오해서 오디오 컨텍스트 키워트 최적화 오디오  거기가 오디오 자바스크립트 오디오 컨텍스트

설명

해당 소스 코드는 구형 자바스크립트(ES5 이하)로 작성되어 있으므로, 만약 최신 환경에 대한 대응이 필요하다면 인터넷 검색 등으로 ES6 이상에 대응하도록 고쳐야 합니다.

 

Step 1: 오디오 컨텍스트, 버퍼 소스 생성
var context = new AudioContext(); 
var source = context.createBufferSource();
  • 버퍼 소스(source)를 통해 오디오 음정을 조절할 수 있습니다.

 

Step 2: 버퍼 저장 변수 및 재생 상태 저장 변수 추가
var buffer1 = null; 
var isPlaying1 = false;
  • 버퍼: 서버로부터 비동기로 받아온 음원의 ArrayBuffer를 재사용하기 위해 저장하는 곳입니다.
  • isPlaying1: 버퍼 소스를 한번 시작하면 재사용이 불가능하기 때문에 재사용을 위해 상태를 현재 재생 상태를 저장합니다.

 

Step 3: 서버로부터 mp3 파일 가져오기, 버퍼 데이터 생성
var request = new XMLHttpRequest();

request.open( 'GET', 'https://음원주소.con/source.mp3', true);
request.responseType = 'arraybuffer';
request.onload = function() {
    context.decodeAudioData(request.response, function(buffer) {
        console.log(buffer);
    buffer1 = buffer;
    }, function(err) { console.log(err); });
}

request.send();
  • 서버의 음원 주소로 요청(request)를 보내 arraybuffer 타입으로 응답(response)을 가져온 뒤, 해당 응답을 buffer1 변수에 저장합니다.

 

Step 4: 음정에 맞춰 transpose한 뒤 음원을 재생하는 함수 만들기
function start1() {
  source = context.createBufferSource();
  source.buffer = buffer1;
  source.connect(context.destination);
  var transpose = parseInt(document.querySelector("#stepper1").value);
  source.detune.value = transpose.value * 100; 
  
  source.start(0);
}
  • BufferSource는 재활용이 불가능하므로 재생 버튼을 누를 때마다 새로 생성해야 합니다.
  • BufferSource의 buffer로 서버에서 가져온 buffer1을 사용합니다.
  • 소스를 오디오 컨텍스트의 도착점(context.destination)과 연결(connect)합니다.
    • 소스와 컨텍스트를 연결해야 스피커에서 소리가 나옵니다.
  • transpose: HTML 코드에 있던 #stepper1 필드로부터 값을 가져옵니다.
  • source.detune.value: 센트(cent)단위로 튜닝을 변경합니다.
    • 1 반음(semitone)은 100센트입니다. transpose의 값에 100을 곱해 반음 단위로 변경합니다.
  • source.start(0): 처음 위치(0)부터 재생을 시작합니다.

 

센트, 반음 단위와 관련된 글은 음악 이론과 관련되어 있어 이 포스트에서 설명을 생략합니다. 아래 포스트에서 일부 내용이 설명되어 있습니다.

 

Step 5: HTML 요소에 이벤트 부여
document.querySelector("#stepper1").addEventListener("change", function() {
  if(isPlaying1) {
    source.stop();
    start1();
  }
});
document.querySelector("#play1").addEventListener("click", function() {
  if(isPlaying1) {
    source.stop();
  } else {
    start1();
  }
    isPlaying1 = !isPlaying1
});
  • 위의 이벤트 리스너는 Transpose의 필드 값(#stepper1)이 변경되었을 때 음원을 멈춘 다음 변경된 음정으로 다시 재생합니다.
  • 아래의 이벤트 리스너는 재생 버튼(#play1)에 할당된 이벤트로 버튼을 누르면 음원을 재생하고, 재생중인 경우 음원을 멈춥니다.

 

 

출처

문의 | 코멘트 또는 yoonbumtae@gmail.com


카테고리: WEB: Frontend


0개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다