//--------------------------------------------------------------------------- // サウンドカードの出力でのオープン // WFX.wFormatTag = WAVE_FORMAT_PCM; // WFX.nChannels = 1; // WFX.wBitsPerSample = 16; // WFX.nSamplesPerSec = 11025; // WFX.nBlockAlign = WORD(WFX.nChannels *(WFX.wBitsPerSample/8)); // WFX.nAvgBytesPerSec = WFX.nBlockAlign * WFX.nSamplesPerSec; // WFX.cbSize = 0; BOOL __fastcall CWave::OutOpen(LPWAVEFORMATEX pWFX, UINT IDDevice, DWORD Size) { if( m_pDLL ){ m_OutOpen = m_pDLL->OutOpen(pWFX->nSamplesPerSec, Size); if( !m_OutOpen ) PumpMessages(); return m_OutOpen; } if( m_OutOpen ) OutAbort(); m_Error = 0; m_OutBCC = 0x7fffffff; m_OutWait = FALSE; m_OutUnder = FALSE; m_OutWP = m_OutRP = m_OutBC = 0; m_OWFX = *pWFX; m_OutLen = Size; m_OutBuffSize = Size * (m_OWFX.wBitsPerSample/8) * m_OWFX.nChannels; m_OutMemSize = sizeof(WAVEHDR) + m_OutBuffSize; if( m_OutMemSize & 3 ) m_OutMemSize += 4 - (m_OutMemSize & 3); m_OutAllocSize = m_OutMemSize * m_OutFifoSize; m_OutEvent = ::CreateEvent(NULL, FALSE,FALSE,NULL); if( (m_Error = ::waveOutOpen( &m_hout, IDDevice , pWFX, (DWORD)WaveOutProc, (DWORD)this, CALLBACK_FUNCTION ) ) != MMSYSERR_NOERROR ){ OutAbort(); return FALSE; } if( (m_Error = ::waveOutPause(m_hout))!= MMSYSERR_NOERROR ){ OutAbort(); return FALSE; } // バッファーの準備 m_pOutBase = new char[m_OutAllocSize]; ::VirtualLock(m_pOutBase, m_OutAllocSize); memset(m_pOutBase, 0, m_OutAllocSize); LPSTR p = m_pOutBase; for(int i = 0; i < m_OutFifoSize; i++, p += m_OutMemSize ){ m_pOutBuff[i] = (WAVEHDR *)p; ((WAVEHDR *)p)->dwBufferLength = m_OutBuffSize; ((WAVEHDR *)p)->dwFlags = 0; ((WAVEHDR *)p)->dwUser = NULL; ((WAVEHDR *)p)->dwLoops = NULL; ((WAVEHDR *)p)->lpData = p + sizeof(WAVEHDR); if( (m_Error = ::waveOutPrepareHeader(m_hout, (WAVEHDR *)p, sizeof(WAVEHDR)) ) != MMSYSERR_NOERROR ){ OutAbort(); return FALSE; } } m_OutOpen = TRUE; m_OutFirst = TRUE; return TRUE; }
//--------------------------------------------------------------------------- BOOL __fastcall CWave::OutWrite(const SHORT *pData) { if( m_pDLL ){ return m_pDLL->OutWrite(pData); } int Len = m_OutLen; int i; if( !m_OutOpen ){ m_Error = 1; return FALSE; } if( m_OutUnder ){ m_Error = 1; OutClose(); return FALSE; } // 送信バッファ空き待ち EnterCriticalSection(&m_OutCS); if( m_OutBC >= m_OutFifoSize ){ m_OutWait++; ::LeaveCriticalSection(&m_OutCS); if( ::WaitForSingleObject( m_OutEvent, WAVE_TIMEOUT_EVENT ) != WAIT_OBJECT_0 ){ m_Error = 2; OutAbort(); return FALSE; } } else { ::LeaveCriticalSection(&m_OutCS); } // データの変換 LPWAVEHDR hp = m_pOutBuff[m_OutWP]; SHORT *wp = (SHORT *)hp->lpData; if( m_OWFX.nChannels == 2 ){ for( i = 0; i < Len; i++ ){ *wp++ = *pData; *wp++ = *pData++; } } else { memcpy(wp, pData, sizeof(SHORT)*Len); } ::waveOutWrite(m_hout, hp, sizeof(WAVEHDR) ); ::EnterCriticalSection(&m_OutCS); // m_OutCS++が1命令では展開されない m_OutBC++; ::LeaveCriticalSection(&m_OutCS); if( m_OutFirst ){ if( (m_OutBC >= 8) || (m_OutBC >= (m_OutFifoSize-1)) ){ m_OutFirst = FALSE; ::waveOutRestart( m_hout ); } } m_OutWP++; if( m_OutWP >= m_OutFifoSize){ m_OutWP = 0; } return TRUE; }