본문 바로가기
Project

[소리 시각화 시키기 2일차] unity audiosource listener volume / audio channels / 유니티 리스너가 듣는 소리 크기 값 얻기

by 배애앰이 좋아 2021. 3. 4.
반응형

 

소리 시각화 1일차 결과들

 

기존 결과 문제점 ([ 소리 시각화 시키기 1일차 ] : 88-it.tistory.com/187) : 

1.구가 일정하게 퍼지지 않고 한 쪽으로 기울어져 있다.

2.옆에 이상한 모양이 생긴다.

 

현재 : 유니티에서 10x10x10 으로 Listener를 이동시키면서 소리 값을 측정해 해당 데이터를 통해 pythoncharm 에서 위와 같은 결과를 구현하였으나 위와 같은 문제점을 나타남.

 

여러 테스트와 측정해본 결과,

데이터를 시각화 시키는 과정의 문제가 아닌, 데이터를 뽑는 과정에서 문제점인 것을 발견

 

위 결과 문제점의 원인 : 기본적인 소리 측정에 대한 문제

 

현재 유니티 내에서 사운드의 volume 값은 제공해주지만, Listener(소리 듣는 사람)가 듣고 있는 소리 값을 따로 유니티 내에서 지원해주지 않습니다. 이를 직접 구하기 위해서는 유니티 내 지원하는 AudioListener.GetOutputData 함수를 통해서 listener 가 듣고 있는 소리의 샘플들을 얻어 계산을 통해 얻을 수 있습니다.

 

여기서 소리 샘플[Sampling]이라는 것은?

소리(Sound)라는 것은 아날로그이기에 Linear 합니다. 컴퓨터는 디지털이므로 이 Linear한 소리를 Discrete 한 데이터로 변환해야 합니다.

 

하지만, 아날로그의 복잡한 특성을 전부 그대로 담기에는 용량의 문제가 있으므로

일부분만 채취(샘플링)하여 최대한 원본과 유사한 디지털 데이터를 만들게 됩니다.

이러한 과정을 샘플링이라 하며 이를 통해 얻어지는 데이터들을 샘플입니다.

 

소리 샘플링 과정 및 샘플

 

<관련 용어>
(1) 샘플링 레이트(Sampling Rate) : 1초에 몇 개의 샘플을 추출할 것인지

(2) Bit Depth : 한 개의 샘플이 얼마만큼의 크기를 가지는지

 

그리고 위 샘플들을 다 더해서 평균을 내면 소리의 크기 값(=샘플의 평균 값) 얻을 수 있습니다.

이 값을 전체 레벨의 평균값이자, RMS value 입니다.

 

RMS(Root Mean Square)는 각 샘플들의 레벨 값을 제곱해서(Square) 평균을 구하고(Mean)
그렇게 얻어진 평균에 제곱한 것을 상쇄시키기 위해 루트를 씌워서(Root) 얻어진
입니다.

 

rms를 구하기 위한 코드 일부분

 

이렇게 평균을 구하는 이유는 소리를 구성하는 각 샘플의 볼륨값들은 일종의 교류 성분들(+-값을 교대로 갖는)이기 때문에 일반적인 평균을 구하는 방식으로 무조건 더해서 평균을 구하면 결국 값이 0(데시벨로 치면 마이너스 무한대)가까워버립니다.

 

이를 막고 의미 있는 값을 구하기 위해 제곱을 해서 모두 양수로 만들어서 평균을 구하는 것입니다.

이렇게 구해진 RMS는 소리 크기가 객관적으로 얼마나 큰지를 확인하는 용도로 많이 사용되며 현재 최종적으로 저희가 얻고자 하는 값입니다.

 

여기서 유니티는 3d 적인 sound 효과(예를 들면, 사용자 기준으로 왼쪽이 소리가 크게 들린다 / 오른쪽이 크게 들린다) 주기 위해 A와 같이 두 가지 channels 을 사용하게 됩니다. 이 채널이 의미하는 바는 한 소리를 오른쪽, 왼쪽 나눈 소리입니다. 그렇기 때문에 유니티 내에서 정확한 RMS valuechannel 1, 0의 각각 값을 구해서 이에 대한 평균값을 가져야합니다.

 

유니티 channel 과 현재 측정하는 방법의 문제점

 

하지만 기존에 이 중에서 한 쪽 channel 0 만 계산하였기 때문에 B 같은 상황에서 Chennel 1까지 측정해야 제대로 된 큰 값이 나오지만 계산하지 않아 작은 값이 나와 결과 적으로 일정한 원형이 안 나오고 쏠리는 현상과 이상하게 측정되는 것을 알 수 있었습니다.

 

또한, 이런 값의 차이는 사운드와 매우 밀접한 거리에서 두드러지게 나타나는 것을 테스트하며 알게 되었으며, 기존 같은 경우는 사운드와 매우 밀접한 거리보다는 조금이라도 거리가 있는 환경에서 테스트를 해보았기 때문에 문제를 발견하지 못하였던 것 같습니다.

 

위와 같은 원인과 문제점을 보완한 최종 코드 :

 

< unity audiosource listener volume / 유니티에서 listener가 듣는 소리값 얻는 코드 >

 

public float[] samples;
AudioSource audio;

audio = GetComponent<AudioSource>();
int qSamples = 4096;
audio.GetOutputData(samples, 0);
float sum = 0;
for (int i = 0; i < samples.Length; i++)
{
  sum += samples[i] * samples[i];
}
return Mathf.Sqrt(sum / qsamples);

 

< 풀코드(사용하지 않는 변수가 포함된 정리되지 않은 코드입니다.) >

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sound1 : MonoBehaviour
{
    public int qsamples = 1024;
    public float refvalue = 0.1f;
    public float rmsvalue;
    public float dbvalue;
    public float volume = 90;
    int factor = 1000;
    public float[] samples;

    AudioSource _audioSource;
    AudioSource audio;
    public float[] _samples = new float[512];

    // Start is called before the first frame update
    void Start()
    {
        samples = new float[qsamples];
        _audioSource = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void GetSpectrumAudioSource()
    {
        _audioSource.GetSpectrumData(_samples, 0, FFTWindow.Blackman);
    }

    public float getVolume2()
    {
        audio = GetComponent<AudioSource>();
        int qSamples = 4096;
        audio.GetOutputData(samples, 0);
        float sum = 0;
        for (int i = 0; i < samples.Length; i++)
        {
            sum += samples[i] * samples[i];
        }
        float v1 =  Mathf.Sqrt(sum / qsamples);
        
        audio.GetOutputData(samples, 1);
        sum = 0;
        for (int i = 0; i < samples.Length; i++)
        {
            sum += samples[i] * samples[i];
        }

        float v2 = Mathf.Sqrt(sum / qsamples);

        return v1 + v2;
    }
}

 

< 위와 같은 원인을 해결한 후 결과들 >

 

배경

 

위 배경으로 빨간색이 사운드이고 밑에 plane이 바닥이라고 설정하였습니다.

 

색갈의 의미 (소리 크기 값)

 

결과 이미지 : 조건 : 없는 경우 / 조건 :  Sound value 2 이하는 자름

 

제일 위의 결과와 다르게 구가 좀더 둥그렇고 이상하게 분화구처럼 생긴 부분이 없어진 것을 확인할 수 있습니다.

 

결과 1. 조건 : 없는 경우 움짤

 

 

결과 2. 조건 : Sound value 2 이하는 자름 움짤

 

 

또 다른 결과 (이 결과는 간단하게 한 페이지로 정리)

 

 

여기까지 마무리하며 지금은 평면 상에서 테스트를 하였다면 다음에는 간단한 지형을 적용시켜서 테스트 해볼 계획입니다. 읽어주셔서 감사합니다.

 

참고한 사이트 :

1. answers.unity.com/questions/221594/how-to-get-audiosource-current-volume-for-a-listen.html

 

How to get current volume of an AudioSource. - Unity Answers

 

answers.unity.com

2. www.cuonet.com/bbs/board.php?bo_table=qna2&wr_id=1301599

 

rms 레벨이 무엇인가요!?

불법 다운 받은 복제 크랙 소프트 관련 사용법 질문 올리시면 아이디 정지 됩니다. 불법 Cubase 5 크랙버젼 질문글 금지!! Palson 님 유튜브 마스터링 강좌보는데저는 지금까지 벌륨피크레벨만 …

www.cuonet.com

3. blog.acu.pe.kr/59

 

[소리/음향] 샘플링(Sampling) 및 관련 이론

[Sampling] 이 세상의 소리(Sound)라는 것은 아날로그이기에 Linear 하다. 그런데 컴퓨터는 디지털이므로 이 Linear한 소리를 Discrete 한 데이터로 변환해야 한다. 아날로그의 오묘하고 복잡한 특성을 전

blog.acu.pe.kr

 

반응형

댓글