static void * winsnd_thread(void *p){ MSSndCard *card=(MSSndCard*)p; WinSndData *d=(WinSndData*)card->data; int bsize=d->rate/8000 * 320; uint8_t *rtmpbuff=NULL; uint8_t *wtmpbuff=NULL; int err; MMRESULT mr = NOERROR; int pos_whdr=0; d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; d->sound_err=winsnd_open(d, d->devid, d->bits,d->stereo,d->rate,&bsize); if (d->sound_err==0){ rtmpbuff=(uint8_t*)alloca(bsize); wtmpbuff=(uint8_t*)alloca(bsize); } while(d->read_started || d->write_started){ if (d->sound_err==0){ if (d->write_started){ #if 0 if (d->stat_output>0 && d->buffer_playing==0) { ms_error("No data currently playing in sound card" ); } if (d->stat_output>0 && (d->stat_input-d->stat_output>10 || d->stat_input-d->stat_output<-10)) ms_error("Not perfectly synchronized (input-output=%i)", d->stat_input-d->stat_output); #endif while (d->buffer_playing<6 && d->buffer_playing<MAX_WAVEHDR) { ms_mutex_lock(&d->mutex); err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); ms_mutex_unlock(&d->mutex); if (err!=bsize) break; ms_mutex_lock(&d->mutex); /* write to sound devide! */ memcpy (d->waveouthdr[pos_whdr].lpData, wtmpbuff, bsize); mr = waveOutWrite (d->waveoutdev, &(d->waveouthdr[pos_whdr]), sizeof (d->waveouthdr[pos_whdr])); if (mr != MMSYSERR_NOERROR) { if (mr == WAVERR_STILLPLAYING) { /* retry later */ /* data should go back to queue */ /* TODO */ ms_warning("sound device write STILL_PLAYING (waveOutWrite:0x%i)", mr); } else { ms_warning("sound device write returned (waveOutWrite:0x%i)", mr); } } else { d->buffer_playing++; pos_whdr++; if (pos_whdr == MAX_WAVEHDR) pos_whdr = 0; /* loop over the prepared blocks */ } ms_mutex_unlock(&d->mutex); if (err<0){ #if !defined(_WIN32_WCE) ms_warning("Fail to write %i bytes from soundcard: %s", bsize,strerror(errno)); #else ms_warning("Fail to write %i bytes from soundcard: %i", bsize,WSAGetLastError()); #endif } } if (d->buffer_playing==6 || d->buffer_playing==MAX_WAVEHDR) { int discarded=0; ms_mutex_lock(&d->mutex); while (d->bufferizer->size>=bsize){ discarded++; d->stat_notplayed++; err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); } ms_mutex_unlock(&d->mutex); if (discarded>0) ms_error("Extra data for sound card removed (%ims), (playing: %i) (input-output: %i)", (discarded*20*320)/320, d->buffer_playing, d->stat_input - d->stat_output); } #if !defined(_WIN32_WCE) Sleep(5); #endif #if defined(_WIN32_WCE) Sleep(10); #endif }else { int discarded=0; /* don't think this is usefull, anyway... */ ms_mutex_lock(&d->mutex); while (d->bufferizer->size>=bsize){ discarded++; err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); } ms_mutex_unlock(&d->mutex); if (discarded>0) ms_error("Extra data for sound card removed (%ims), (playing: %i) (input-output: %i)", (discarded*20)/320, d->buffer_playing, d->stat_input - d->stat_output); Sleep(10); } }else Sleep(10); } if (d->sound_err==0) { int i; int count=0; /* close sound card */ ms_error("Shutting down sound device (playing: %i) (input-output: %i) (notplayed: %i)", d->buffer_playing, d->stat_input - d->stat_output, d->stat_notplayed); /* unprepare buffer */ for (i = 0; i < MAX_WAVEHDR; i++) { int counttry=0; for (counttry=0;counttry<10;counttry++) { mr = waveInUnprepareHeader (d->waveindev, &(d->waveinhdr[i]), sizeof (d->waveinhdr[i])); if (mr != MMSYSERR_NOERROR) { ms_error("Failed to unprepared %i buffer from sound card (waveInUnprepareHeader:0x%i", count, mr); Sleep (20); } else { count++; ms_message("successfully unprepared %i buffer from sound card.", count); break; } } } ms_warning("unprepared %i buffer from sound card.", count); mr = waveInStop (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_error("failed to stop recording sound card (waveInStop:0x%i)", mr); } else { ms_message("successfully stopped recording sound card"); } mr = waveInReset (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("failed to reset recording sound card (waveInReset:0x%i)", mr); } else { ms_message("successful reset of recording sound card"); } mr = waveInClose (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("failed to close recording sound card (waveInClose:0x%i)", mr); } else { ms_message("successfully closed recording sound card"); } d->sound_err=-1; } d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; return NULL; }
long audio_file_read(Chan *c, void *va, long count, vlong offset) { MMRESULT status; long len = av.in.buf * Audio_Max_Buf / Audio_Max_Val; char *v = (char *) va; char *p; long ba, n, chunk, total; qlock(&flag_lock); WaitForSingleObject(inlock, INFINITE); if(waserror()) { audioerror(waveInStop(audio_file_in), AUDIOIN, "audio_file_read Stop 1"); audioerror(waveInReset(audio_file_in), AUDIOIN, "audio_file_read Reset 1"); audioerror(waveInUnprepareHeader(audio_file_in, &audio_ping.hdr, sizeof(WAVEHDR)), AUDIOIN, "in unprepare ping"); audioerror(waveInUnprepareHeader(audio_file_in, &audio_pong.hdr, sizeof(WAVEHDR)), AUDIOIN, "in unprepare pong"); audio_ping.sz = 0; audio_ping.ptr = &audio_ping.data[0]; audio_pong.sz = 0; audio_pong.ptr = &audio_pong.data[0]; ping_is_filling = pong_is_filling = 0; paddle = Ping; qunlock(&flag_lock); ReleaseMutex(inlock); nexterror(); } if(!(audio_flags & INISOPEN)) error(Eperm); /* check for block alignment */ ba = av.in.bits * av.in.chan / Bits_Per_Byte; if(len < 1 || count % ba) error(Ebadarg); if(!(audio_flags & INPUTISGOING)) { if(audioerror(waveInStart(audio_file_in), AUDIOIN, "in start") == -1) error(Eio); audio_ping.sz = 0; audio_ping.ptr = &audio_ping.data[0]; audio_ping.hdr.lpData = audio_ping.ptr; audio_ping.hdr.dwBufferLength = len; audio_ping.hdr.dwUser = Ping; audio_ping.hdr.dwFlags = 0; status = waveInPrepareHeader(audio_file_in, &audio_ping.hdr, sizeof(WAVEHDR)); if (audioerror(status, AUDIOIN, "in prepare header") == -1) error(Eio); audio_pong.sz = 0; audio_pong.ptr = &audio_pong.data[0]; audio_pong.hdr.lpData = audio_pong.ptr; audio_pong.hdr.dwBufferLength = len; audio_pong.hdr.dwUser = Pong; audio_pong.hdr.dwFlags = 0; status = waveInPrepareHeader(audio_file_in, &audio_pong.hdr, sizeof(WAVEHDR)); if (audioerror(status, AUDIOIN, "in prepare header") == -1) error(Eio); status = waveInAddBuffer(audio_file_in, &audio_ping.hdr, sizeof(WAVEHDR)); if (audioerror(status, AUDIOIN, "file_read Add Buffer")== -1) { waveInUnprepareHeader(audio_file_in, &audio_ping.hdr, sizeof(WAVEHDR)); audio_ping.sz = 0; audio_ping.ptr = &audio_ping.data[0]; error(Eio); } ping_is_filling = 1; pong_is_filling = 0; paddle = Ping; audio_flags |= INPUTISGOING; } poperror(); ReleaseMutex(inlock); total = 0; Draining: WaitForSingleObject(inlock, INFINITE); if(waserror()) { audioerror(waveInStop(audio_file_in), AUDIOIN, "audio_file_read Stop 2"); audioerror(waveInReset(audio_file_in), AUDIOIN, "audio_file_read Reset 2"); audioerror(waveInUnprepareHeader(audio_file_in, &audio_ping.hdr, sizeof(WAVEHDR)), AUDIOIN, "in unprepare ping"); audioerror(waveInUnprepareHeader(audio_file_in, &audio_pong.hdr, sizeof(WAVEHDR)), AUDIOIN, "in unprepare pong"); audio_ping.sz = 0; audio_ping.ptr = &audio_ping.data[0]; audio_pong.sz = 0; audio_pong.ptr = &audio_pong.data[0]; audio_flags &= ~INPUTISGOING; ReleaseMutex(inlock); qunlock(&flag_lock); nexterror(); } while((total < count) && ((audio_ping.sz > 0) || (audio_pong.sz > 0))) { n = paddle == Ping ? audio_ping.sz : audio_pong.sz; p = paddle == Ping ? audio_ping.ptr : audio_pong.ptr; chunk = min(n, count - total); memmove(v+total, p , chunk); total += chunk; if(paddle == Ping) { if(!pong_is_filling) { if(audioerror(waveInAddBuffer(audio_file_in, &audio_pong.hdr, sizeof(WAVEHDR)), AUDIOIN, "draining ping calling add buffer pong") == -1) error(Eio); pong_is_filling = 1; } audio_ping.sz -= chunk; if(audio_ping.sz > 0) { audio_ping.ptr += chunk; } else { audio_ping.ptr = &audio_ping.data[0]; ping_is_filling = 0; paddle = Pong; } } else { if(!ping_is_filling) { if(audioerror(waveInAddBuffer(audio_file_in, &audio_ping.hdr, sizeof(WAVEHDR)), AUDIOIN, "draining pong calling add buffer ping") == -1) error(Eio); ping_is_filling = 1; } audio_pong.sz -= chunk; if(audio_pong.sz > 0) { audio_pong.ptr += chunk; } else { audio_pong.ptr = &audio_pong.data[0]; pong_is_filling = 0; paddle = Ping; } } } poperror(); ReleaseMutex(inlock); if(total == count) { qunlock(&flag_lock); return count; } Filling: WaitForSingleObject(inlock, INFINITE); while((audio_ping.sz < 1) && (audio_pong.sz < 1)) { ReleaseMutex(inlock); sleep(0); goto Filling; } ReleaseMutex(inlock); goto Draining; }
static void wave_in_test_deviceIn(int device, WAVEFORMATEX *pwfx, DWORD format, DWORD flags, WAVEINCAPSA *pcaps) { HWAVEIN win; HANDLE hevent = CreateEventW(NULL, FALSE, FALSE, NULL); WAVEHDR frag; MMRESULT rc; DWORD res; MMTIME mmt; WORD nChannels = pwfx->nChannels; WORD wBitsPerSample = pwfx->wBitsPerSample; DWORD nSamplesPerSec = pwfx->nSamplesPerSec; win=NULL; rc=waveInOpen(&win,device,pwfx,(DWORD_PTR)hevent,0,CALLBACK_EVENT|flags); /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */ ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER || rc==MMSYSERR_ALLOCATED || ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && (flags & WAVE_FORMAT_DIRECT) && !(pcaps->dwFormats & format)) || ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && (!(flags & WAVE_FORMAT_DIRECT) || (flags & WAVE_MAPPED)) && !(pcaps->dwFormats & format)) || (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)), "waveInOpen(%s): format=%dx%2dx%d flags=%x(%s) rc=%s\n", dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample, pwfx->nChannels,CALLBACK_EVENT|flags, wave_open_flags(CALLBACK_EVENT|flags),wave_in_error(rc)); if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & format)) trace(" Reason: The device lists this format as supported in its " "capabilities but opening it failed.\n"); if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && !(pcaps->dwFormats & format)) trace("waveInOpen(%s): format=%dx%2dx%d %s rc=%s failed but format " "not supported so OK.\n",dev_name(device),pwfx->nSamplesPerSec, pwfx->wBitsPerSample,pwfx->nChannels, flags & WAVE_FORMAT_DIRECT ? "flags=WAVE_FORMAT_DIRECT" : flags & WAVE_MAPPED ? "flags=WAVE_MAPPED" : "", mmsys_error(rc)); if (rc!=MMSYSERR_NOERROR) { CloseHandle(hevent); return; } res=WaitForSingleObject(hevent,1000); ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for open\n"); ok(pwfx->nChannels==nChannels && pwfx->wBitsPerSample==wBitsPerSample && pwfx->nSamplesPerSec==nSamplesPerSec, "got the wrong format: %dx%2dx%d instead of %dx%2dx%d\n", pwfx->nSamplesPerSec, pwfx->wBitsPerSample, pwfx->nChannels, nSamplesPerSec, wBitsPerSample, nChannels); /* Check that the position is 0 at start */ check_position(device, win, 0, pwfx); frag.lpData=HeapAlloc(GetProcessHeap(), 0, pwfx->nAvgBytesPerSec); frag.dwBufferLength=pwfx->nAvgBytesPerSec; frag.dwBytesRecorded=0; frag.dwUser=0; frag.dwFlags=0; frag.dwLoops=0; frag.lpNext=0; rc=waveInPrepareHeader(win, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR, "waveInPrepareHeader(%s): rc=%s\n", dev_name(device),wave_in_error(rc)); ok(frag.dwFlags&WHDR_PREPARED,"waveInPrepareHeader(%s): prepared flag " "not set\n",dev_name(device)); if (winetest_interactive && rc==MMSYSERR_NOERROR) { trace("Recording for 1 second at %5dx%2dx%d %s %s\n", pwfx->nSamplesPerSec, pwfx->wBitsPerSample,pwfx->nChannels, get_format_str(pwfx->wFormatTag), flags & WAVE_FORMAT_DIRECT ? "WAVE_FORMAT_DIRECT" : flags & WAVE_MAPPED ? "WAVE_MAPPED" : ""); rc=waveInAddBuffer(win, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer(%s): rc=%s\n", dev_name(device),wave_in_error(rc)); /* Check that the position is 0 at start */ check_position(device, win, 0, pwfx); rc=waveInStart(win); ok(rc==MMSYSERR_NOERROR,"waveInStart(%s): rc=%s\n", dev_name(device),wave_in_error(rc)); res = WaitForSingleObject(hevent,1200); ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for header\n"); ok(frag.dwFlags&WHDR_DONE,"WHDR_DONE not set in frag.dwFlags\n"); ok(frag.dwBytesRecorded==pwfx->nAvgBytesPerSec, "frag.dwBytesRecorded=%d, should=%d\n", frag.dwBytesRecorded,pwfx->nAvgBytesPerSec); mmt.wType = TIME_BYTES; rc=waveInGetPosition(win, &mmt, sizeof(mmt)); ok(rc==MMSYSERR_NOERROR,"waveInGetPosition(%s): rc=%s\n", dev_name(device),wave_in_error(rc)); ok(mmt.wType == TIME_BYTES, "doesn't support TIME_BYTES: %u\n", mmt.wType); ok(mmt.u.cb == frag.dwBytesRecorded, "Got wrong position: %u\n", mmt.u.cb); /* stop playing on error */ if (res!=WAIT_OBJECT_0) { rc=waveInStop(win); ok(rc==MMSYSERR_NOERROR, "waveInStop(%s): rc=%s\n",dev_name(device),wave_in_error(rc)); } } rc=waveInUnprepareHeader(win, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR,"waveInUnprepareHeader(%s): rc=%s\n", dev_name(device),wave_in_error(rc)); rc=waveInClose(win); ok(rc==MMSYSERR_NOERROR, "waveInClose(%s): rc=%s\n",dev_name(device),wave_in_error(rc)); res=WaitForSingleObject(hevent,1000); ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for close\n"); if (winetest_interactive) { /* * Now play back what we recorded */ HWAVEOUT wout; trace("Playing back recorded sound\n"); rc=waveOutOpen(&wout,WAVE_MAPPER,pwfx,(DWORD_PTR)hevent,0,CALLBACK_EVENT); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER || rc==MMSYSERR_ALLOCATED || ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && !(pcaps->dwFormats & format)), "waveOutOpen(%s) format=%dx%2dx%d flags=%x(%s) rc=%s\n", dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample, pwfx->nChannels,CALLBACK_EVENT|flags, wave_open_flags(CALLBACK_EVENT),wave_out_error(rc)); if (rc==MMSYSERR_NOERROR) { rc=waveOutPrepareHeader(wout, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR,"waveOutPrepareHeader(%s): rc=%s\n", dev_name(device),wave_out_error(rc)); if (rc==MMSYSERR_NOERROR) { WaitForSingleObject(hevent,INFINITE); rc=waveOutWrite(wout, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR,"waveOutWrite(%s): rc=%s\n", dev_name(device),wave_out_error(rc)); WaitForSingleObject(hevent,INFINITE); rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag)); ok(rc==MMSYSERR_NOERROR,"waveOutUnprepareHeader(%s): rc=%s\n", dev_name(device),wave_out_error(rc)); } rc=waveOutClose(wout); ok(rc==MMSYSERR_NOERROR,"waveOutClose(%s): rc=%s\n", dev_name(device),wave_out_error(rc)); } else trace("Unable to play back the recorded sound\n"); } HeapFree(GetProcessHeap(), 0, frag.lpData); CloseHandle(hevent); }
/////////////////////////////////////////////// // // // メイン関数 // // // /////////////////////////////////////////////// int main(void){ ///////////////////////////////// // // // リアルタイム入出力用変数 // // // ///////////////////////////////// char key; // スルーと処理音の切替用変数 int in1; // 入力バッファ番号 int out1; // 出力バッファ番号 int flag; // 入出力状態のフラグ int n; // バッファ用の時刻 short in_buf[NUM_BUF][BUF_SIZE]={0}; // 入力バッファ WAVEHDR in_hdr[NUM_BUF]; // 入力バッファのヘッダ HWAVEIN in_hdl = 0; // 入力(録音)デバイスのハンドル short out_buf[NUM_BUF][BUF_SIZE]={0}; // 出力バッファ WAVEHDR out_hdr[NUM_BUF]; // 出力バッファのヘッダ HWAVEOUT out_hdl = 0; // 出力(再生)デバイスのハンドル WAVEFORMATEX wave_format_ex = {WAVE_FORMAT_PCM, // PCM 1, // モノラル Fs, // サンプリング周波数 2*Fs, // 1秒あたりの音データサイズ(byte) 2, // 音データの最小単位(2byte) 16, // 量子化ビット(16bit) 0 // オプション情報のサイズ(0byte) }; //************************************************************************// /////////////////////////////// // // // 信号処理用変数 // // // /////////////////////////////// int t = 0; // 入力の時刻 int to = 0; // 出力の時刻 int hflg= 0; // 素通しと処理音の状態フラグ int i; // forループ用変数 double s[MEM_SIZE+1]={0}; // 入力データ格納用変数 double y[MEM_SIZE+1]={0}; // 出力データ格納用変数 long int l; // FFT用変数 double w[FFT_SIZE+1] ={0}; // 窓関数 double x[FFT_SIZE+1] ={0}; // FFTの入力 double x1[FFT_SIZE+1]={0}; // 半フレームシフト時の入力保持用 double z1[FFT_SIZE+1]={0}; // ハーフオーバーラップの出力保持用 double Xphs[FFT_SIZE+1]={0}; double Xpow; // 区間パワー /////////////////////////////// // // // 変数の初期設定 // // // /////////////////////////////// init(); //ビット反転,乗み係数の計算 l = 0; // FFT開始時刻管理 for(i=0;i<FFT_SIZE;i++){ // 窓関数の設定 w[i]=0.5*(1.0-cos(2.0*M_PI*i/(double)FFT_SIZE)); } //************************************************************************// /////////////////////////////////////// // // // 入出力デバイスのオープン // // // /////////////////////////////////////// waveInOpen(&in_hdl, 0, &wave_format_ex, 0, 0, CALLBACK_NULL); // 入力(録音)デバイスオープン for (i = 0; i < NUM_BUF; i++){ memset(&in_hdr[i], 0, sizeof(WAVEHDR)); // 全入力バッファを初期化 } waveOutOpen(&out_hdl, 0, &wave_format_ex, 0, 0, CALLBACK_NULL); // 出力(再生)デバイスオープン waveOutPause(out_hdl); // サウンドデバイスの一時停止 for (i = 0; i < NUM_BUF; i++){ // 全出力バッファを初期化 memset(&out_hdr[i], 0, sizeof(WAVEHDR)); } /////////////////////////////////////// // // // 入出力バッファの初期設定 // // // /////////////////////////////////////// for (i=0;i<NUM_BUF;i++){ // バッファの数だけ繰り返し out_hdr[i].lpData = (char *)out_buf[i]; // 出力バッファデータを更新 out_hdr[i].dwBufferLength = BUF_SIZE * 2; // 出力バッファサイズを設定 out_hdr[i].dwFlags = 0; // 出力フラグのクリア waveOutPrepareHeader(out_hdl, &out_hdr[i], sizeof(WAVEHDR));// 出力バッファをロック waveOutWrite(out_hdl, &out_hdr[i], sizeof(WAVEHDR)); // 出力バッファを出力待ちキューに送信 in_hdr[i].lpData = (char *)in_buf[i]; // 入力バッファデータの更新 in_hdr[i].dwBufferLength = BUF_SIZE * 2; // 入力バッファサイズを設定 in_hdr[i].dwFlags = 0; // 入力フラグのクリア waveInPrepareHeader(in_hdl, &in_hdr[i], sizeof(WAVEHDR)); // 入力バッファをロック waveInAddBuffer(in_hdl, &in_hdr[i], sizeof(WAVEHDR)); // 入力バッファを入力待ちキューに送信 } waveOutRestart(out_hdl); // 音声出力開始 waveInStart(in_hdl); // 音声入力開始 in1 = 0; // 入力バッファ番号の初期化 out1 = 0; // 出力バッファ番号の初期化 flag = 0; // 入出力判定フラグを0(入力)とする printf("[space]--> Through <=> Processing\n"); // [space]で処理切り替え printf("[Enter]--> End\n"); // [Enter]で終了 printf("Through\n"); // 素通しであることを表示 /////////////////////////////////// // // // メインループ // // // /////////////////////////////////// while (1){ ////////////////////////// // // // 出力書出し処理 // // // ////////////////////////// if (flag == 1){ // flag=1なら出力状態 if ((out_hdr[out1].dwFlags & WHDR_DONE) != 0){ // 出力バッファのフラグ情報が0でないなら処理を実行 for (n = 0; n < BUF_SIZE; n++){ // 出力をBUF_SIZEサンプル分だけ書き出す to=(to+1)%MEM_SIZE; // 出力時刻の更新 out_buf[out1][n] = y[to]*32768; // 出力データを記録 } waveOutUnprepareHeader(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); // 出力バッファをクリーンアップ out_hdr[out1].lpData = (char *)out_buf[out1]; // 出力データを更新 // out_hdr[out1].dwBufferLength = BUF_SIZE * 2; // 出力バッファサイズを設定 out_hdr[out1].dwFlags = 0; // 出力バッファのフラグ情報を0にする waveOutPrepareHeader(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); // 情報を更新し出力バッファを準備 waveOutWrite(out_hdl, &out_hdr[out1], sizeof(WAVEHDR));// 出力待ちキューに出力バッファデータを送信 out1=(out1+1)%NUM_BUF; // 出力バッファ番号を更新 flag = 0; // 入出力フラグを flag=0 (入力状態) にする } } ////////////////////////// // // // 入力読込み処理 // // // ////////////////////////// if ((in_hdr[in1].dwFlags & WHDR_DONE) != 0){ // 入力バッファのフラグ情報が0でないなら処理を実行 waveInUnprepareHeader(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 録音済みの入力バッファを選択 for (n = 0; n < BUF_SIZE; n++){ // BUF_SIZEサンプル分の入力を読込み,処理する t=(t+1)%MEM_SIZE; // 入力時刻の更新 s[t] = in_buf[in1][n]/32768.0; // 入力バッファからデータ読み込み (正規化) y[t] = s[t]; // 出力=入力の素通しをつくる if(hflg!=0){ // 処理状態フラグが0以外なら信号処理を実行 //************************************************************************// //////////////////////////////////////////////////// // // // Signal Processing // // // // 現在時刻tの入力 s[t] から出力 y[t] をつくる // // // // ※ tは0からMEM_SIZE-1までをループ // // // //////////////////////////////////////////////////// x[l] = x1[l]; // FFT_SIZE/2までの入力をx[l]に格納 x1[l]= x[FFT_SIZE/2+l]=s[t]; // FFT_SIZE/2以降の入力をx[l]に格納 y[t] = (z[l]+z1[l])/FFT_SIZE; // IFFTで得た出力 z1[l]= z[FFT_SIZE/2+l]; // ハーフオーバーラップ用に出力記録 if( l>=FFT_SIZE/2){ // 半フレームごとにFFTを実行 Xpow=0; for(i=0;i<FFT_SIZE;i++){ xin[i]=x[i]*w[i]; // 窓関数をかける Xpow = Xpow+xin[i]*xin[i]; // 区間パワー計算 } fft(); // FFT /////////////////////////// // // // FFT処理 // // // /////////////////////////// for(i=0;i<FFT_SIZE/2;i++){ Xphs[i] = 2*M_PI*(double)rand()/RAND_MAX;// 位相スペクトルを一様乱数で設定 Xphs[FFT_SIZE-i]=-Xphs[i]; // 奇対称にする } for(i=0;i<FFT_SIZE;i++){ Xr[i]=Xpow/4.0*cos(2*M_PI*i/FFT_SIZE+Xphs[i]); //実部の処理.複素分離とオーバーラップのため4で割る Xi[i]=Xpow/4.0*sin(2*M_PI*i/FFT_SIZE+Xphs[i]); //虚部の処理.複素分離とオーバーラップのため4で割る } ifft(); // IFFT l=0; } l++; // FFT用の時刻管理 //************************************************************************// y[t]=atan(y[t])/(M_PI/2.0); // クリップ防止 } } in_hdr[in1].dwFlags = 0; // 入力バッファのフラグ情報を0にする waveInPrepareHeader(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 情報を更新し入力バッファを準備 waveInAddBuffer(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 入力待ちキューに入力バッファデータを送信 in1=(in1+1)%NUM_BUF; // 入力バッファの更新 flag = 1; // 入出力フラグを flag=1 (出力状態)にする } //////////////////////////////////////////////////// // // // キーボード入力に対する処理の設定 // // // // // // [デフォルト設定] // // ・スペースキーで素通しと信号処理を切り替え // // ・Enterキーでプログラム終了 // // // //////////////////////////////////////////////////// if (kbhit()){ // キーボード入力があったか key = getch(); // キーのチェック if (key == 32){ // スペースキーが押されとき hflg=(hflg+1)%2; // 処理フラグ変更 if(hflg==1) printf("Processing\n"); // 処理中であることを表示 else printf("Through\n"); // 素通しであることを表示 } if (key == 13){ // Enterキーが押されたとき waveInStop(in_hdl); // 入力を停止 for (i = 0; i < NUM_BUF; i++){ // 全入力バッファのアンロック if ((in_hdr[i].dwFlags & WHDR_PREPARED) != 0){ waveInUnprepareHeader(in_hdl, &in_hdr[i], sizeof(WAVEHDR )); } } waveInClose(in_hdl); // 入力(録音)デバイスのクローズ waveOutPause(out_hdl); // 出力を停止 for (i = 0; i < NUM_BUF; i++){ if ((out_hdr[i].dwFlags & WHDR_PREPARED) != 0){ // 全出力バッファのアンロック waveOutUnprepareHeader(out_hdl, &out_hdr[i], sizeof(WAVEHDR)); } } waveOutClose(out_hdl); // 出力(再生)デバイスのクローズ return 0; } } } //メインループ終わり }
static void WinMMStopCapture(ALCdevice *pDevice) { WinMMData *pData = (WinMMData*)pDevice->ExtraData; waveInStop(pData->hWaveHandle.In); }
static DWORD widStop(WAVEMAPDATA* wim) { TRACE("(%p)\n", wim); return waveInStop(wim->u.in.hInnerWave); }
int main(void){ ///////////////////////////////// // // // リアルタイム入出力用変数 // // // ///////////////////////////////// char key; // スルーと処理音の切替用変数 int in1; // 入力バッファ番号 int out1; // 出力バッファ番号 int flag; // 入出力状態のフラグ int n; // バッファ用の時刻 short in_buf[NUM_BUF][BUF_SIZE]={0}; // 入力バッファ WAVEHDR in_hdr[NUM_BUF]; // 入力バッファのヘッダ HWAVEIN in_hdl = 0; // 入力(録音)デバイスのハンドル short out_buf[NUM_BUF][BUF_SIZE]={0}; // 出力バッファ WAVEHDR out_hdr[NUM_BUF]; // 出力バッファのヘッダ HWAVEOUT out_hdl = 0; // 出力(再生)デバイスのハンドル WAVEFORMATEX wave_format_ex = {WAVE_FORMAT_PCM, // PCM 1, // モノラル Fs, // サンプリング周波数 2*Fs, // 1秒あたりの音データサイズ(byte) 2, // 音データの最小単位(2byte) 16, // 量子化ビット(16bit) 0 // オプション情報のサイズ(0byte) }; //************************************************************************// /////////////////////////////// // // // 信号処理用変数 // // // /////////////////////////////// int t = 0; // 入力の時刻 int to = 0; // 出力の時刻 int hflg= 0; // 素通しと処理音の状態フラグ int i; // forループ用変数 double s[MEM_SIZE+1]={0}; // 入力データ格納用変数 double y[MEM_SIZE+1]={0}; // 出力データ格納用変数 long int l=0; // 変調用正弦波の時刻 int tau; // 遅延時間 double d,depth, r; // 遅延の深さと周波数 /////////////////////////////// // // // 変数の初期設定 // // // /////////////////////////////// d = 0.002*Fs; // ビブラートの基本深さ depth= 0.002*Fs; // 変化の深さ r = 0.5; // 周波数 //************************************************************************// /////////////////////////////////////// // // // 入出力デバイスのオープン // // // /////////////////////////////////////// waveInOpen(&in_hdl, 0, &wave_format_ex, 0, 0, CALLBACK_NULL); // 入力(録音)デバイスオープン for (i = 0; i < NUM_BUF; i++){ memset(&in_hdr[i], 0, sizeof(WAVEHDR)); // 全入力バッファを初期化 } waveOutOpen(&out_hdl, 0, &wave_format_ex, 0, 0, CALLBACK_NULL); // 出力(再生)デバイスオープン waveOutPause(out_hdl); // サウンドデバイスの一時停止 for (i = 0; i < NUM_BUF; i++){ // 全出力バッファを初期化 memset(&out_hdr[i], 0, sizeof(WAVEHDR)); } /////////////////////////////////////// // // // 入出力バッファの初期設定 // // // /////////////////////////////////////// for (i=0;i<NUM_BUF;i++){ // バッファの数だけ繰り返し out_hdr[i].lpData = (char *)out_buf[i]; // 出力バッファデータを更新 out_hdr[i].dwBufferLength = BUF_SIZE * 2; // 出力バッファサイズを設定 out_hdr[i].dwFlags = 0; // 出力フラグのクリア waveOutPrepareHeader(out_hdl, &out_hdr[i], sizeof(WAVEHDR));// 出力バッファをロック waveOutWrite(out_hdl, &out_hdr[i], sizeof(WAVEHDR)); // 出力バッファを出力待ちキューに送信 in_hdr[i].lpData = (char *)in_buf[i]; // 入力バッファデータの更新 in_hdr[i].dwBufferLength = BUF_SIZE * 2; // 入力バッファサイズを設定 in_hdr[i].dwFlags = 0; // 入力フラグのクリア waveInPrepareHeader(in_hdl, &in_hdr[i], sizeof(WAVEHDR)); // 入力バッファをロック waveInAddBuffer(in_hdl, &in_hdr[i], sizeof(WAVEHDR)); // 入力バッファを入力待ちキューに送信 } waveOutRestart(out_hdl); // 音声出力開始 waveInStart(in_hdl); // 音声入力開始 in1 = 0; // 入力バッファ番号の初期化 out1 = 0; // 出力バッファ番号の初期化 flag = 0; // 入出力判定フラグを0(入力)とする printf("[space]--> Through <=> Processing\n"); // [space]で処理切り替え printf("[Enter]--> End\n"); // [Enter]で終了 printf("Through\n"); // 素通しであることを表示 /////////////////////////////////// // // // メインループ // // // /////////////////////////////////// while (1){ ////////////////////////// // // // 出力書出し処理 // // // ////////////////////////// if (flag == 1){ // flag=1なら出力状態 if ((out_hdr[out1].dwFlags & WHDR_DONE) != 0){ // 出力バッファのフラグ情報が0でないなら処理を実行 for (n = 0; n < BUF_SIZE; n++){ // 出力をBUF_SIZEサンプル分だけ書き出す to=(to+1)%MEM_SIZE; // 出力時刻の更新 out_buf[out1][n] = y[to]*32768; // 出力データを記録 } waveOutUnprepareHeader(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); // 出力バッファをクリーンアップ out_hdr[out1].lpData = (char *)out_buf[out1]; // 出力データを更新 // out_hdr[out1].dwBufferLength = BUF_SIZE * 2; // 出力バッファサイズを設定 out_hdr[out1].dwFlags = 0; // 出力バッファのフラグ情報を0にする waveOutPrepareHeader(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); // 情報を更新し出力バッファを準備 waveOutWrite(out_hdl, &out_hdr[out1], sizeof(WAVEHDR));// 出力待ちキューに出力バッファデータを送信 out1=(out1+1)%NUM_BUF; // 出力バッファ番号を更新 flag = 0; // 入出力フラグを flag=0 (入力状態) にする } } ////////////////////////// // // // 入力読込み処理 // // // ////////////////////////// if ((in_hdr[in1].dwFlags & WHDR_DONE) != 0){ // 入力バッファのフラグ情報が0でないなら処理を実行 waveInUnprepareHeader(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 録音済みの入力バッファを選択 for (n = 0; n < BUF_SIZE; n++){ // BUF_SIZEサンプル分の入力を読込み,処理する t=(t+1)%MEM_SIZE; // 入力時刻の更新 s[t] = in_buf[in1][n]/32768.0; // 入力バッファからデータ読み込み (正規化) y[t] = s[t]; // 出力=入力の素通しをつくる if(hflg!=0){ // 処理状態フラグが0以外なら信号処理を実行 //************************************************************************// //////////////////////////////////////////////////// // // // Signal Processing // // // // 現在時刻tの入力 s[t] から出力 y[t] をつくる // // // // ※ tは0からMEM_SIZE-1までをループ // // // //////////////////////////////////////////////////// tau = d + depth*sin(2.0*M_PI*r*l/(double)Fs); // 遅延時間の設定 y[t] = s[t]+s[(t-tau+MEM_SIZE)%MEM_SIZE]; // 遅延信号と現在の信号を加算 l = (l+1)%(10*Fs); // 変調用正弦波の時刻管理 //************************************************************************// y[t]=atan(y[t])/(M_PI/2.0); // クリップ防止 } } in_hdr[in1].dwFlags = 0; // 入力バッファのフラグ情報を0にする waveInPrepareHeader(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 情報を更新し入力バッファを準備 waveInAddBuffer(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 入力待ちキューに入力バッファデータを送信 in1=(in1+1)%NUM_BUF; // 入力バッファの更新 flag = 1; // 入出力フラグを flag=1 (出力状態)にする } //////////////////////////////////////////////////// // // // キーボード入力に対する処理の設定 // // // // // // [デフォルト設定] // // ・スペースキーで素通しと信号処理を切り替え // // ・Enterキーでプログラム終了 // // // //////////////////////////////////////////////////// if (kbhit()){ // キーボード入力があったか key = getch(); // キーのチェック if (key == 32){ // スペースキーが押されとき hflg=(hflg+1)%2; // 処理フラグ変更 if(hflg==1) printf("Processing\n"); // 処理中であることを表示 else printf("Through\n"); // 素通しであることを表示 } if (key == 13){ // Enterキーが押されたとき waveInStop(in_hdl); // 入力を停止 for (i = 0; i < NUM_BUF; i++){ // 全入力バッファのアンロック if ((in_hdr[i].dwFlags & WHDR_PREPARED) != 0){ waveInUnprepareHeader(in_hdl, &in_hdr[i], sizeof(WAVEHDR )); } } waveInClose(in_hdl); // 入力(録音)デバイスのクローズ waveOutPause(out_hdl); // 出力を停止 for (i = 0; i < NUM_BUF; i++){ if ((out_hdr[i].dwFlags & WHDR_PREPARED) != 0){ // 全出力バッファのアンロック waveOutUnprepareHeader(out_hdl, &out_hdr[i], sizeof(WAVEHDR)); } } waveOutClose(out_hdl); // 出力(再生)デバイスのクローズ return 0; } } } //メインループ終わり }
int main(void){ ///////////////////////////////// // // // リアルタイム入出力用変数 // // // ///////////////////////////////// char key; // スルーと処理音の切替用変数 int in1; // 入力バッファ番号 int out1; // 出力バッファ番号 int flag; // 入出力状態のフラグ int n; // バッファ用の時刻 short in_buf[NUM_BUF][BUF_SIZE]={0}; // 入力バッファ WAVEHDR in_hdr[NUM_BUF]; // 入力バッファのヘッダ HWAVEIN in_hdl = 0; // 入力(録音)デバイスのハンドル short out_buf[NUM_BUF][BUF_SIZE]={0}; // 出力バッファ WAVEHDR out_hdr[NUM_BUF]; // 出力バッファのヘッダ HWAVEOUT out_hdl = 0; // 出力(再生)デバイスのハンドル WAVEFORMATEX wave_format_ex = {WAVE_FORMAT_PCM, // PCM 1, // モノラル Fs, // サンプリング周波数 2*Fs, // 1秒あたりの音データサイズ(byte) 2, // 音データの最小単位(2byte) 16, // 量子化ビット(16bit) 0 // オプション情報のサイズ(0byte) }; //************************************************************************// /////////////////////////////// // // // 信号処理用変数 // // // /////////////////////////////// int t = 0; // 入力の時刻 int to = 0; // 出力の時刻 int hflg= 0; // 素通しと処理音の状態フラグ int i; // forループ用変数 double s[MEM_SIZE+1]={0}; // 入力データ格納用変数 double y[MEM_SIZE+1]={0}; // 出力データ格納用変数 double rho[P+1]={0}, delta[P+1]={0}, sigma[P+1]={0}; // AR係数推定 double h[P+1]={0}, r[N+1]={0}, a[P+1][P+1]={0}; // 自己相関関数 int l, m, tau; // 繰り返し計算管理用 double rs[MEM_SIZE+1]={0}; // 合成信号 double rmax; // ピッチ抽出用 int pitch; // ピッチ double e[N+1]={0}; // 予測誤差 double k, alpha; // ピッチ変更用の変数 /////////////////////////////// // // // 変数の初期設定 // // // /////////////////////////////// h[0] = 1.0; // 線形予測係数h[0]=1 alpha = 2.0; // 高さを何倍にするか k = 0; // 出力時刻管理 //************************************************************************// /////////////////////////////////////// // // // 入出力デバイスのオープン // // // /////////////////////////////////////// waveInOpen(&in_hdl, 0, &wave_format_ex, 0, 0, CALLBACK_NULL); // 入力(録音)デバイスオープン for (i = 0; i < NUM_BUF; i++){ memset(&in_hdr[i], 0, sizeof(WAVEHDR)); // 全入力バッファを初期化 } waveOutOpen(&out_hdl, 0, &wave_format_ex, 0, 0, CALLBACK_NULL); // 出力(再生)デバイスオープン waveOutPause(out_hdl); // サウンドデバイスの一時停止 for (i = 0; i < NUM_BUF; i++){ // 全出力バッファを初期化 memset(&out_hdr[i], 0, sizeof(WAVEHDR)); } /////////////////////////////////////// // // // 入出力バッファの初期設定 // // // /////////////////////////////////////// for (i=0;i<NUM_BUF;i++){ // バッファの数だけ繰り返し out_hdr[i].lpData = (char *)out_buf[i]; // 出力バッファデータを更新 out_hdr[i].dwBufferLength = BUF_SIZE * 2; // 出力バッファサイズを設定 out_hdr[i].dwFlags = 0; // 出力フラグのクリア waveOutPrepareHeader(out_hdl, &out_hdr[i], sizeof(WAVEHDR));// 出力バッファをロック waveOutWrite(out_hdl, &out_hdr[i], sizeof(WAVEHDR)); // 出力バッファを出力待ちキューに送信 in_hdr[i].lpData = (char *)in_buf[i]; // 入力バッファデータの更新 in_hdr[i].dwBufferLength = BUF_SIZE * 2; // 入力バッファサイズを設定 in_hdr[i].dwFlags = 0; // 入力フラグのクリア waveInPrepareHeader(in_hdl, &in_hdr[i], sizeof(WAVEHDR)); // 入力バッファをロック waveInAddBuffer(in_hdl, &in_hdr[i], sizeof(WAVEHDR)); // 入力バッファを入力待ちキューに送信 } waveOutRestart(out_hdl); // 音声出力開始 waveInStart(in_hdl); // 音声入力開始 in1 = 0; // 入力バッファ番号の初期化 out1 = 0; // 出力バッファ番号の初期化 flag = 0; // 入出力判定フラグを0(入力)とする printf("[space]--> Through <=> Processing\n"); // [space]で処理切り替え printf("[Enter]--> End\n"); // [Enter]で終了 printf("Through\n"); // 素通しであることを表示 /////////////////////////////////// // // // メインループ // // // /////////////////////////////////// while (1){ ////////////////////////// // // // 出力書出し処理 // // // ////////////////////////// if (flag == 1){ // flag=1なら出力状態 if ((out_hdr[out1].dwFlags & WHDR_DONE) != 0){ // 出力バッファのフラグ情報が0でないなら処理を実行 for (n = 0; n < BUF_SIZE; n++){ // 出力をBUF_SIZEサンプル分だけ書き出す to=(to+1)%MEM_SIZE; // 出力時刻の更新 out_buf[out1][n] = y[to]*32768; // 出力データを記録 } waveOutUnprepareHeader(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); // 出力バッファをクリーンアップ out_hdr[out1].lpData = (char *)out_buf[out1]; // 出力データを更新 // out_hdr[out1].dwBufferLength = BUF_SIZE * 2; // 出力バッファサイズを設定 out_hdr[out1].dwFlags = 0; // 出力バッファのフラグ情報を0にする waveOutPrepareHeader(out_hdl, &out_hdr[out1], sizeof(WAVEHDR)); // 情報を更新し出力バッファを準備 waveOutWrite(out_hdl, &out_hdr[out1], sizeof(WAVEHDR));// 出力待ちキューに出力バッファデータを送信 out1=(out1+1)%NUM_BUF; // 出力バッファ番号を更新 flag = 0; // 入出力フラグを flag=0 (入力状態) にする } } ////////////////////////// // // // 入力読込み処理 // // // ////////////////////////// if ((in_hdr[in1].dwFlags & WHDR_DONE) != 0){ // 入力バッファのフラグ情報が0でないなら処理を実行 waveInUnprepareHeader(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 録音済みの入力バッファを選択 for (n = 0; n < BUF_SIZE; n++){ // BUF_SIZEサンプル分の入力を読込み,処理する t=(t+1)%MEM_SIZE; // 入力時刻の更新 s[t] = in_buf[in1][n]/32768.0; // 入力バッファからデータ読み込み (正規化) y[t] = s[t]; // 出力=入力の素通しをつくる if(hflg!=0){ // 処理状態フラグが1なら信号処理を実行 //************************************************************************// //////////////////////////////////////////////////// // // // Signal Processing // // // // 現在時刻tの入力 s[t] から出力 y[t] をつくる // // // // ※ tは0からMEM_SIZE-1までをループ // // // //////////////////////////////////////////////////// if(l>=N){ // Nサンプルごとに線形予測分析を実行 ///////////////////////////// // // // 線形予測分析 // // // ///////////////////////////// pitch=1, rmax=0; // ピッチの初期化 for(tau=0;tau<N;tau++){ // 時間差tauの設定 r[tau]=0; // 自己相関の初期化 i=0; while(tau+i<=N){ // 自己相関の計算 r[tau]=r[tau]+s[(t-i+MEM_SIZE)%MEM_SIZE]*s[(t-tau-i+MEM_SIZE)%MEM_SIZE]; i++; } r[tau]=r[tau]/N; // 自己相関の初期化 //ピッチ抽出 if(tau>=20 && rmax<r[tau]){ // 音声ピッチの範囲内で最大相関検出 rmax=r[tau]; pitch=tau; // ピッチ推定値 } } // レビンソン・ダービンアルゴリズム sigma[0]=r[0]; // sigma[0] = 時間差0の自己相関関数 for(m=0;m<P;m++){ delta[m+1]=r[m+1]; // deltaの初期値 = 自己相関関数 for(i=1;i<=m;i++){ delta[m+1]=delta[m+1]+a[m][i]*r[m+1-i]; // AR係数aを使ってdeltaを更新 } if(fabs(sigma[m])==0.0 || fabs(delta[m+1])>2*fabs(sigma[m])){ rho[m+1] =0.0; // deltaが0かsigmaの2倍より大きい場合はrho=0 a[m+1][m+1]=rho[m+1]; // AR係数をrhoにする } else{ rho[m+1]=-delta[m+1]/sigma[m]; // 反射係数rhoの更新 a[m+1][m+1]=rho[m+1]; // AR係数a[m+1]の更新 } sigma[m+1]=sigma[m]*(1.0-(rho[m+1]*rho[m+1]));// sigma[m+1]の更新 for(i=1;i<=m;i++){ a[m+1][i]=a[m][i]+rho[m+1]*a[m][m+1-i];// AR係数a[1]からa[m]の更新 } } h[0]=1.0; // 線形予測係数h[0] for(i=1;i<=P;i++){ h[i]=a[P][i]; // 線形予測係数h[1]からh[P]の計算 } l=0; } e[l]=0; for(i=0;i<=P;i++){ e[l] = e[l] + h[i]*s[(t-i+MEM_SIZE)%MEM_SIZE];// 予測誤差(音源) } l++; ///////////////////////////// // // // 音声合成 // // // ///////////////////////////// rs[t]=e[(int)k]; // 音源の設定 for(i=1;i<=P;i++){ rs[t] = rs[t] - h[i]*rs[(t-i+MEM_SIZE)%MEM_SIZE];// 音声合成 } y[t]=rs[t]; // 合成音声を出力 k = k+alpha; // 出力の時刻インデックス if(k>=N)k=k-N; // kを0からNの範囲内にする //////////////////////////////////////////////////// // // // Signal Processing // // // // ここまで // // // //////////////////////////////////////////////////// //************************************************************************// y[t]=atan(y[t])/(M_PI/2.0); // クリップ防止 } } in_hdr[in1].dwFlags = 0; // 入力バッファのフラグ情報を0にする waveInPrepareHeader(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 情報を更新し入力バッファを準備 waveInAddBuffer(in_hdl, &in_hdr[in1], sizeof(WAVEHDR)); // 入力待ちキューに入力バッファデータを送信 in1=(in1+1)%NUM_BUF; // 入力バッファの更新 flag = 1; // 入出力フラグを flag=1 (出力状態)にする } //////////////////////////////////////////////////// // // // キーボード入力に対する処理の設定 // // // // // // [デフォルト設定] // // ・スペースキーで素通しと信号処理を切り替え // // ・Enterキーでプログラム終了 // // // //////////////////////////////////////////////////// if (kbhit()){ // キーボード入力があったか key = getch(); // キーのチェック if (key == 32){ // スペースキーが押されとき hflg=(hflg+1)%2; // 処理フラグ変更 if(hflg==1) printf("Processing\n"); // 処理中であることを表示 else printf("Through\n"); // 素通しであることを表示 } if (key == 13){ // Enterキーが押されたとき waveInStop(in_hdl); // 入力を停止 for (i = 0; i < NUM_BUF; i++){ // 全入力バッファのアンロック if ((in_hdr[i].dwFlags & WHDR_PREPARED) != 0){ waveInUnprepareHeader(in_hdl, &in_hdr[i], sizeof(WAVEHDR )); } } waveInClose(in_hdl); // 入力(録音)デバイスのクローズ waveOutPause(out_hdl); // 出力を停止 for (i = 0; i < NUM_BUF; i++){ if ((out_hdr[i].dwFlags & WHDR_PREPARED) != 0){ // 全出力バッファのアンロック waveOutUnprepareHeader(out_hdl, &out_hdr[i], sizeof(WAVEHDR)); } } waveOutClose(out_hdl); // 出力(再生)デバイスのクローズ return 0; } } } //メインループ終わり }
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: // Get the window and client dimensions GetClientRect(hWnd, &window.rect); int width = window.rect.right - window.rect.left; int height = window.rect.bottom - window.rect.top; // Create status bar status.hwnd = CreateWindow(STATUSCLASSNAME, " Turn knob to adjust measurement frequency", WS_VISIBLE | WS_CHILD, 0, 0, 0, 0, hWnd, (HMENU)STATUS_ID, hInst, NULL); // Create tooltip tooltip.hwnd = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWnd, NULL, hInst, NULL); SetWindowPos(tooltip.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); tooltip.info.cbSize = sizeof(tooltip.info); tooltip.info.hwnd = hWnd; tooltip.info.uFlags = TTF_IDISHWND | TTF_SUBCLASS; // Create scale scale.hwnd = CreateWindow(WC_STATIC, NULL, WS_VISIBLE | WS_CHILD | SS_NOTIFY | SS_OWNERDRAW, 8, 8, 160, 40, hWnd, (HMENU)SCALE_ID, hInst, NULL); // Add scale to tooltip tooltip.info.uId = (UINT_PTR)scale.hwnd; tooltip.info.lpszText = "Frequency scale"; SendMessage(tooltip.hwnd, TTM_ADDTOOL, 0, (LPARAM) &tooltip.info); // Create knob knob.hwnd = CreateWindow(KNOBCLASS, NULL, WS_VISIBLE | WS_CHILD, 4, 52, 168, 168, hWnd, (HMENU)KNOB_ID, hInst, NULL); // Add knob to tooltip tooltip.info.uId = (UINT_PTR)knob.hwnd; tooltip.info.lpszText = "Frequency adjustment knob"; SendMessage(tooltip.hwnd, TTM_ADDTOOL, 0, (LPARAM) &tooltip.info); // Create display display.hwnd = CreateWindow(WC_STATIC, NULL, WS_VISIBLE | WS_CHILD | SS_NOTIFY | SS_OWNERDRAW, 176, 8, width - 184, 50, hWnd, (HMENU)DISPLAY_ID, hInst, NULL); // Add display to tooltip tooltip.info.uId = (UINT_PTR)display.hwnd; tooltip.info.lpszText = "Frequency and level display"; SendMessage(tooltip.hwnd, TTM_ADDTOOL, 0, (LPARAM) &tooltip.info); // Create meter meter.hwnd = CreateWindow(WC_STATIC, NULL, WS_VISIBLE | WS_CHILD | SS_NOTIFY | SS_OWNERDRAW, 176, 66, width - 184, 50, hWnd, (HMENU)METER_ID, hInst, NULL); // Add meter to tooltip tooltip.info.uId = (UINT_PTR)meter.hwnd; tooltip.info.lpszText = "Level meter"; SendMessage(tooltip.hwnd, TTM_ADDTOOL, 0, (LPARAM) &tooltip.info); // Create meter slider meter.slider.hwnd = CreateWindow(TRACKBAR_CLASS, NULL, WS_VISIBLE | WS_CHILD | TBS_HORZ | TBS_NOTICKS | TBS_TOP, 178, 92, width - 188, 20, hWnd, (HMENU)SLIDER_ID, hInst, NULL); SendMessage(meter.slider.hwnd, TBM_SETRANGE, TRUE, MAKELONG(MIN_METER, MAX_METER)); SendMessage(meter.slider.hwnd, TBM_SETPOS, TRUE, MIN_METER); // Add slider to tooltip tooltip.info.uId = (UINT_PTR)meter.slider.hwnd; tooltip.info.lpszText = "Level meter"; SendMessage(tooltip.hwnd, TTM_ADDTOOL, 0, (LPARAM) &tooltip.info); // Create spectrum spectrum.hwnd = CreateWindow(WC_STATIC, NULL, WS_VISIBLE | WS_CHILD | SS_NOTIFY | SS_OWNERDRAW, 176, 122, width - 184, 50, hWnd, (HMENU)SPECTRUM_ID, hInst, NULL); // Add spectrum to tooltip tooltip.info.uId = (UINT_PTR)spectrum.hwnd; tooltip.info.lpszText = "Frequency spectrum"; SendMessage(tooltip.hwnd, TTM_ADDTOOL, 0, (LPARAM) &tooltip.info); // Create quit button quit.hwnd = CreateWindow(WC_BUTTON, "Quit", WS_VISIBLE | WS_CHILD, width - 80, 194, 72, 24, hWnd, (HMENU)QUIT_ID, hInst, NULL); // Start audio thread audio.thread = CreateThread(NULL, 0, AudioThread, hWnd, 0, &audio.id); // Start meter timer CreateTimerQueueTimer(&meter.timer, NULL, (WAITORTIMERCALLBACK)MeterCallback, &meter, METER_DELAY, METER_DELAY, WT_EXECUTEDEFAULT); // Update frequency UpdateFrequency(); break; // Colour static text case WM_CTLCOLORSTATIC: return (LRESULT)GetSysColorBrush(COLOR_WINDOW); break; // Draw item case WM_DRAWITEM: return DrawItem(wParam, lParam); break; // Disable menus by capturing this message case WM_INITMENU: break; // Capture system character key to stop pop up menus and other // nonsense case WM_SYSCHAR: break; // Char pressed case WM_CHAR: CharPressed(wParam, lParam); break; // Key pressed case WM_KEYDOWN: KeyDown(wParam, lParam); break; // Buttons case WM_COMMAND: switch (LOWORD(wParam)) { // Quit case QUIT_ID: waveInStop(audio.hwi); waveInClose(audio.hwi); PostQuitMessage(0); break; } break; // Notify case WM_NOTIFY: switch (((LPNMHDR)lParam)->code) { // Tooltip case TTN_SHOW: TooltipShow(wParam, lParam); break; case TTN_POP: TooltipPop(wParam, lParam); break; } break; // Process other messages. case WM_DESTROY: waveInStop(audio.hwi); waveInClose(audio.hwi); PostQuitMessage(0); break; // Everything else default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; }