Jyaiko1.1で
WAVEファイルを再生する 2.タイミング関係を、設定する ........................... } if(wav_data.wave_on) g_ControlDlg.GetButton(IDC_BUTTON_WAVE_READ)->GetElement(1)->TextureColor.States[
DXUT_STATE_NORMAL ]
} read_wave_data(data->fp,l_channel,r_channel); ::ResetEvent(wave_event); //一回だけ読み込むために、eventをresetする g_ControlDlg.GetButton(IDC_BUTTON_WAVE_READ)->GetElement(1)->TextureColor.States[
DXUT_STATE_NORMAL ]
data->wave_on=false; return 0; } if( inputBuffer == NULL
) data_origin.gain_left=
(g_HUD.GetSlider(IDC_SLIDER_GAIN)->GetValue()/10000.0); for( i = 0 ;i < Capture_Data_Length;i++
) //計算の、スレッド開始 for(i=0;i<Capture_Data_Length;i++) } } while(1) //arrange FFT for(i=0;i<2048;i++)
左側の 'WAV read' ボタンを押してwave fileを再生しています。
1.Jyaiko1.1で wavefileを再生する
'WAV_read'のボタンを押すと、wavefileが、Jyaiko1.1上で再生されます。(FFT結果も、橙色の表示に変わります。色は、私の好みですねん。)
wavefileの最後に到達すると、自動的に終了して、realtimeのFFT結果表示に戻ります。
先ず、WAVE
DATAを、配列 l_channel[2048],r_channel[2048]に移します。
そのために、先ず別スレッドを立てる。eventも設定します。
INT
WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance, LPSTR
szCmdLine, int
iCmdShow)
{
g_wav_read_thread=::CreateThread(NULL,0,wave_read,(LPVOID)&wav_data,CREATE_SUSPENDED,&d);
wave_event=::CreateEvent(0,true,false,NULL);
............................
}
wavefileをreadする部分は、こうしました。(適宜、一回だけ、読み込むように、後で仕掛けします。)
void read_wave_data(FILE *fp,float *l_channel,float
*r_channel)
{
int i=0;
int j=0;
for(i;i<4096;i++)
{
if(i%2)
{
fread(r_channel+j,sizeof(float),1,fp);
j++;
}
else
{
fread(l_channel+j,sizeof(float),1,fp);
}
}
この void read_wave_data(FILE *fp,float
*l_channel,float
*r_channel)を何時、実行するかのタイミングですが
とにかく、一回実行して、l_channel[] ,
r_channel[]に読み込ませます。
// ボタンを押したときの eventです。
case
IDC_BUTTON_WAVE_READ:
{
wav_data.wave_on=!wav_data.wave_on;
{
=g_ControlDlg.GetButton(IDC_BUTTON_WAVE_READ)->GetElement(1)->TextureColor.States[
DXUT_STATE_MOUSEOVER ]
=D3DCOLOR_ARGB(255,252,202,130);
wav_data.fp=read_wave_format_chunk(L"LSB2.wav",wav_data.loop_number,wav_data.rest_data_number);
if(wav_data.fp
!=NULL)
{
::ResumeThread(g_wav_read_thread); //wavfileを読み込むスレッドを起動する
::SetEvent(wave_event);//manual
reset //ここで、一回読み込むためのeventをsetする
}
wav_data.wave_start=true;
}
else
{
::SuspendThread(g_wav_read_thread);
g_ControlDlg.GetButton(IDC_BUTTON_WAVE_READ)->GetElement(1)->TextureColor.States[
DXUT_STATE_NORMAL ]
=g_ControlDlg.GetButton(IDC_BUTTON_WAVE_READ)->GetElement(1)->TextureColor.States[
DXUT_STATE_MOUSEOVER ]
=D3DCOLOR_ARGB(255,121,224,200);
wav_data.k=0;
wav_data.wave_start=false;
close_file(wav_data.fp);
}
::SetEvent(wave_event); の部分が、一回読み込むための引き金になります。
当然、wavfileのデータを読み込む部分には、引き金を受け付ける仕掛けが必要です。
以下が、wavefileデータを読み込むスレッドです。
DWORD
WINAPI wave_read(LPVOID x)
{
wav_read_data*
data=(wav_read_data*)x;
while(1)
{
for(data->k=0;
data->k < data->loop_number;
data->k++)
{
::WaitForSingleObject(wave_event,INFINITE);// ここで、待ち受ける
}
// 以下は、最後尾のデータを読み込んで、停止するためのものです。
if(data->k==data->loop_number)
//wave read end & stop
{
::WaitForSingleObject(wave_event,INFINITE);
read_rest_wave_data(data->fp,l_channel,r_channel,data->rest_data_number
);
::ResetEvent(wave_event);
data->k=0;
=g_ControlDlg.GetButton(IDC_BUTTON_WAVE_READ)->GetElement(1)->TextureColor.States[
DXUT_STATE_MOUSEOVER ]
=D3DCOLOR_ARGB(255,121,224,200);
data->wave_start=false;
close_file(wav_data.fp);
}
}
そして、2048個のデータを読み込んだら、停止するように ::ResetEvent(wave_event); と、仕掛けておきます。
このデータを正しく再現するために、PortaudioのCallback関数を利用します。
PortaudioのCallback関数は、そのsampling周期に応じた、データの取り込み、再生を、してくれるはずだからです。
青色の部分が wavefileデータを読み込む所です。
static int pa_test_Callback(const
void *inputBuffer,void
*outputBuffer,
unsigned long
framesPerBuffer,
const PaStreamCallbackTimeInfo*
timeInfo,
PaStreamCallbackFlags
statusFlags,
void
*userData)
{
//paTestData *data =
(paTestData*)userData;
float *out =
(float*)outputBuffer;
float *in =
(float*)inputBuffer;
{
for( i=0;
i<Capture_Data_Length; i++
)
{
*out++ =
SAMPLE_SILENCE;
}
}
else
{
{
if(wav_data.wave_start)
{
//入力を受け付けるのみ
scope_fft_Q[i]=
data_origin.current_Q[i]=data_origin.gain_left * l_channel[i];//left
in++;
scope_fft_I[i]=data_origin.current_I[i]=r_channel[i];//right
in++;<
br> scope_fft_I[i]=data_origin.current_I[i]=(scope_fft_I[i]+
scope_fft_Q[i]*phase_sin
)*inv_cos;
}
else
{
//リアルタイム時の入力を受け付けるのみ
scope_fft_Q[i]=
data_origin.current_Q[i]=data_origin.gain_left * *in;//left
in++;
scope_fft_I[i]=data_origin.current_I[i]=*in;//right
in++;<
br> scope_fft_I[i]=data_origin.current_I[i]=(scope_fft_I[i]+
scope_fft_Q[i]*phase_sin
)*inv_cos;
}
}
::SetEvent(thread_event);//manual
reset
{
*out++=data_origin.output[i]*data_origin.gain;
*out++=data_origin.output[i]*data_origin.gain;
<br> }
return paContinue;
そして、赤色の部分 ::SetEvent(thread_event) は、元々存在する、計算のスレッドを起動してくれます。
この計算のスレッドで、再び、
wavefileデータを読み込むスレッドを起動して、
一回だけ、(2048個のL_channel,
r_channel)読み込みます。
DWORD WINAPI myThread(LPVOID x)
{
{
::WaitForSingleObject(thread_event,INFINITE);
EnterCriticalSection(§ion);
//data
->FFT
data_origin.myfir->get_CaptureData_FFT_result(data_origin.current_I,data_origin.current_Q,2048,data_origin.result,work,ip,w);
///////////////////////////////////////////////////////////////
if(wav_data.wave_start)
::SetEvent(wave_event);//manual
reset
///////////////////////////////////////////////////////////////
..............................
}
この、タイミングの設定で、無事、wavefileを読み込み、音声データも、正常に再現されました。
うーむ、とにかく、出来ましたが、物足りませんね.....
loop できない、部分的に再現できてない....等 キリがないにゃあ。
H.20.5.16