トップページ > 記事閲覧
特定の周波数の音量取得
名前:BayLeaf 日時: 2017/05/18 17:30

いつもお世話になっております。 周波数ごとに表示するサウンドプレーヤーを組み込みたいと考えています。 現状は以下のような感じで作成しようと思っています。 ■■ ■■■■■ ■■■■■■ 0Hz←→16kHz (■は各周波数のボリューム) サウンドハンドルの再生周波数を取得する関数があることは知っているのですが、 再生しているサウンドハンドルで特定の周波数の音量を取得する関数が見つからなかったので質問させていただきました。 Windows版、Android版どちらでも構わないのでやり方があれば教えていただけると幸いです。
メンテ

Page: 1 |

Re: 特定の周波数の音量取得 ( No.1 )
名前:管理人 日時:2017/05/20 23:05

GetFFTVibrationSoftSound という関数で各周波数域での音量を取得することができます ただ、引数で渡すのはサウンドハンドルではなく、ソフトウエアサウンドハンドルなので、 LoadSoundMem で取得できるサウンドハンドルとは別に、 LoadSoftSound を使用してソフトウエアサウンドハンドルも取得しておく必要があります GetFFTVibrationSoftSound を実装した当時の解説を載せますので、よろしければご覧ください m(_ _)m ------------------------------------------------------------------------------ // ソフトウエアで扱う波形データハンドルの指定の範囲を高速フーリエ変換を行い、各周波数域の振幅を取得する // SoftSoundHandle : ソフトサウンドハンドル // Channel : フーリエ変換を行うチャンネル( -1 を指定するとすべてのチャンネルを合成した結果になります ) // SamplePosition : フーリエ変換で使用するサンプルの範囲の開始サンプル位置 // SampleNum : フーリエ変換で使用するサンプルの数( 256, 512, 1024, 2048, 4096, 8192, 16384 の何れかである必要があります ) // Buffer : フーリエ変換を行った結果を代入する float 型配列の先頭アドレス // BufferLength : Buffer の配列の長さ、こちらは長さに制限はありません int GetFFTVibrationSoftSound( int SoftSoundHandle, int Channel, int SamplePosition, int SampleNum, float *Buffer_Array, int BufferLength ) ; 指定のサンプル位置から指定のサンプル数を使って、周波数毎の音量レベルを取得( Buffer配列に代入 )します SampleNum は値が大きいほど多くのサンプルを使って( 多くの再生時間分を使って )フーリエ変換をするので、 音量表示の反応を考えると 4096 くらいが丁度良いです GetFFTVibrationSoftSound を使って画面に周波数毎の音量レベルを描画するサンプルを作成してみましたので、 よろしければご覧ください m(_ _)m ( プログラム中の TestBGM.wav をお手持ちのサウンドファイルに変更してください ) #include "DxLib.h" #include <math.h> #define BUFFERLENGTH 800 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int SoundHandle ; int SoftSoundHandle ; float ParamList[ BUFFERLENGTH ] ; int SamplePos ; int i ; // ウインドウモードで起動 ChangeWindowMode( TRUE ) ; // 画面解像度をセット SetGraphMode( 800, 600, 32 ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) return -1 ; // サウンドファイルをソフトサウンドハンドルとして読み込み SoftSoundHandle = LoadSoftSound( "TestBGM.wav" ) ; // ソフトサウンドハンドルからサウンドハンドルを作成( もう一度ファイルから読み込んでも同じです ) SoundHandle = LoadSoundMemFromSoftSound( SoftSoundHandle ) ; // サウンドの再生開始 PlaySoundMem( SoundHandle, DX_PLAYTYPE_LOOP ) ; // 描画先を裏画面に変更 SetDrawScreen( DX_SCREEN_BACK ) ; // メインループ while( ProcessMessage() == 0 ) { // 画面を初期化 ClearDrawScreen() ; // 現在の再生位置を取得 SamplePos = GetCurrentPositionSoundMem( SoundHandle ) ; // 現在の再生位置から 4096 サンプルを使用して周波数分布を得る GetFFTVibrationSoftSound( SoftSoundHandle, -1, SamplePos, 4096, ParamList, BUFFERLENGTH ) ; // 周波数分布を画面に描画する for( i = 0 ; i < BUFFERLENGTH ; i ++ ) { float Param ; // 関数から取得できる値を描画に適した値に調整 Param = pow( ParamList[ i ], 0.5f ) * 4.0f ; // 縦線を描画 DrawBox( i, 600 - ( int )( Param * 600 ), i + 1, 600, GetColor( 255,255,0 ), TRUE ) ; } // 裏画面の内容を表画面に反映 ScreenFlip() ; } // DXライブラリの後始末 DxLib_End() ; // ソフトの終了 return 0 ; }
メンテ
Re: 特定の周波数の音量取得 ( No.2 )
名前:BayLeaf 日時:2017/05/21 10:16

プログラムまで付けていただきありがとうございます。 早速Android版で実行してしてみたところ上記のプログラムでは実行することができました。 ただ、非同期処理関数(SetUseASyncLoadFlag)を使って読み込みした場合、ロードが終わっていたとしても LoadSoundMemFromSoftSound関数を呼び出すとその後の音声再生ができないときがありました。 因みに配列を使用しているのでそれなりにデータ量が重いです。 ご確認をお願いします。
メンテ
Re: 特定の周波数の音量取得 ( No.3 )
名前:管理人 日時:2017/05/21 21:54

> ただ、非同期処理関数(SetUseASyncLoadFlag)を使って読み込みした場合、ロードが終わっていたとしても > LoadSoundMemFromSoftSound関数を呼び出すとその後の音声再生ができないときがありました。 LoadSoftSound が非同期で行われますので、LoadSoftSound の呼び出しと LoadSoundMemFromSoftSound の 呼び出しの間に読み込み完了のチェックを行っていただければ正常に LoadSoundMemFromSoftSound が実行され、 音声再生ができないということはなくなると思います ( 読み込みが完了していないソフトサウンドハンドルを LoadSoundMemFromSoftSound に渡すと、  正常にサウンドハンドルが作成されませんので )
メンテ
Re: 特定の周波数の音量取得 ( No.4 )
名前:BayLeaf(解決) 日時:2017/06/03 01:36

遅くなりましたが、上記については解決しましたので報告しておきます。 因みにサイズの軽い音声ファイルだと問題が発生しませんでしたが、 サイズの大きい音声ファイル(4分以上のwavファイル)を複数非同期読み込みした際に 読み込みが失敗してしまっていました。 そこで、複数回に分けて読み込むことにしましたところ正常に読み込むことができました。 少々気になることではありますが、読み込み失敗の件については不都合が生じた際にまた質問します。 とりあえずやりたいことはできたので解決とさせていただきます。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存