2022年05月13日

Raw Audio Data を使って自分の音声を可視化してみる

Agora.ioではSDKの他に、ユーザーの入室制限や、チャネルの利用状況を確認できるDashboard RESTful APIがあります。

公式ドキュメント(英文)

システム組み込みにおいて利用頻度の高い機能をピックアップします。

お役立ち資料ダウンロード

オンライン体験におけるブイキューブの技術サポートのご案内

【図解】システム開発のお手伝い

ブイキューブのソリューションアーキテクトが、寄り添います!
各種ライブ配信システムのアーキテクチャについて わかりやすい構成図にてご紹介!

無料ダウンロード

実装

1.AudioRawDataObserver を登録し、コールバックを設定する

今回は自身の音声データを使うので、複数あるコールバックのうち
SetOnRecordAudioFrameCallback を設定します。

TestHelloUnityVideo.cs
    public void setUpRawAudioData() {
            mAudioManager = AudioRawDataManager.GetInstance(mRtcEngine);
    
            // Registers the audio observer.
            mAudioManager.RegisterAudioRawDataObserver();
    
            // Listens for the OnRecordAudioFrameHandler delegate.
            mAudioManager.SetOnRecordAudioFrameCallback(OnRecordAudioFrameHandler);
        }
    

RegisterAudioRawDataObserver は JoinChannel 前にコールしておく必要があります。

TestHelloUnityVideo.cs
    public void join(string channel)
        {
            ... 
    
            setUpRawAudioData();
    
            // join channel
            mRtcEngine.JoinChannel(channel, null, 0);
    
            ... 
        }
    

2.コールバックを実装する

コールバックを設定すると、定期的に AudioFrame が引数で渡されてきます。AudioFrame はサンプリングされた音声データを含むオブジェクトで、これを一時的にためておくキューをクラス内に用意しておきます。今回、キューに格納されたデータは描画のタイミングで 1 個ずつ順番に取り出す実装にしますが、万が一描画のタイミングが遅いなどしてデータが増えすぎてしまわないよう、キューに格納できる上限を設けておきます。

TestHelloUnityVideo.cs
    public void OnRecordAudioFrameHandler(AudioFrame audioFrame) {  
            if(audioFrameQueue.Count <= 3) {
                audioFrameQueue.Enqueue(audioFrame);
            }
        }
    

3.オーディオデータ取得のインターフェースを実装する

今回、音声波形の描画は TestHome.cs に任せるため、AudioFrame オブジェクトを返すメソッドを用意します。

TestHelloUnityVideo.cs
    public AudioFrame getAudioFrame() {
            return (audioFrameQueue.Count > 0) ? (AudioFrame)audioFrameQueue.Dequeue() : new AudioFrame();
        }
    

4.描画ロジックを実装する

LineRenderer を使って音声波形を描画します。先ずは、線の色・太さを設定します。

TestHome.cs
    void Start()
        {
            ...
    
            LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();
    
            float lineWidth = 0.1f;
            lineRenderer.startWidth = lineWidth;
            lineRenderer.endWidth = lineWidth;
    
            Color lineColor = new Color(0.9f, 0.9f, 0.5f);
            lineRenderer.startColor = lineColor;
            lineRenderer.endColor = lineColor;
    
            lineRenderer.material = new Material(Shader.Find("Sprites/Default"));
        }
    

次に Update() メソッドに描画ロジックを追加します。AudioFrame オブジェクトを扱うので、次の一行をファイルに追加しておきます:

TestHome.cs
using agora_gaming_rtc;
    

AudioFrame に含まれるサンプル数と同じサイズの Vector3 配列 (頂点リスト)を用意し、各頂点の座標を計算していきます。サンプル一つ一つは 16 bit PCM 方式で格納されているため、復号してから Y 座標を計算していきます。

TestHome.cs
    void Update()
        {
            ...
    
            if(app != null) {
                AudioFrame audioFrame = app.getAudioFrame();
                LineRenderer lineRenderer = GetComponent<LineRenderer>();
    
                lineRenderer.positionCount = audioFrame.samples;
                Vector3[] points = new Vector3[lineRenderer.positionCount];
    
                float xStretch = 8.0f;
                float yAmp = 2.0f;
                float yOffset = 4.0f;
    
                for(int i = 0, idx = 0; i < lineRenderer.positionCount; i++, idx+=2) {
                    // AudioFrame type is PCM 16bit little endian.
                    short audioLevel = (short) ( (audioFrame.buffer[idx+1] << 8) | audioFrame.buffer[idx] ); 
    
                    points[i] = new Vector3(
                        xStretch * (2.0f * i / (lineRenderer.positionCount - 1.0f) - 1.0f), 
                        yAmp * (audioLevel / 32768f) + yOffset, 
                        0.0f
                    );
                }
    
                lineRenderer.SetPositions(points);
            }
        }
    

実行結果

ガイドブックダウンロード
ビデオ通話・ライブ配信API/SDK「Agora」

超低遅延API/SDK「Agora」ガイドブック

通話・配信遅延30-200ms!100万人の視聴対応!未経験者から専門家まで、誰でも読みやすいAgoraのガイドブックをダウンロードしませんか。

無料ダウンロード
ブイキューブ

執筆者ブイキューブ

Agoraの日本総代理店として、配信/通話SDKの提供だけでなく、導入支援から行い幅広いコミュニケーションサービスに携わっている。

関連記事

先頭へ戻る