Exemple #1
0
long
audio_file_write(Chan *c, void *va, long count, vlong offset)
{
    MMRESULT status;
    WAVEHDR *hHdr = (WAVEHDR *) NULL;
    char *hData = NULL;
    char *p = (char *) va;
    long ba;
    long bufsz;
    long chunk;
    long total;

    qlock(&flag_lock);
    if(waserror()) {
        qunlock(&flag_lock);
        nexterror();
    }

    if(!(audio_flags & OUTISOPEN))
        error(Eperm);

    /* check for block alignment */
    ba = av.out.bits * av.out.chan / Bits_Per_Byte;

    if(count % ba)
        error(Ebadarg);

    bufsz = av.out.buf * Audio_Max_Buf / Audio_Max_Val;

    if(bufsz < 1)
        error(Ebadarg);

    total = 0;

    while(total < count) {

Again:
        chunk = min(bufsz, count - total);

Drain:
        WaitForSingleObject(outlock, INFINITE);
        while(out_buf_count > bufsz) {
            ReleaseMutex(outlock);
            sleep(0);
            goto Drain;
        }

        if(out_buf_count == 0)
            audioerror(waveOutReset(audio_file_out), AUDIOOUT, "wave out reset");
        ReleaseMutex(outlock);

        /*
         * allocate and lock the memory for the wave header
         * and data blocks
         */
        hHdr = (WAVEHDR *) malloc(sizeof(WAVEHDR));
        if (!hHdr)
            error(Enomem);

        hData = malloc(chunk);
        if (!hData) {
            free(hHdr);
            error(Enomem);
        }

        /*
         * initialize the wave header struct
         */

        /*
         * copy user data into write Q
         */
        memmove(hData, p+total, chunk);

        hHdr->lpData = hData;
        hHdr->dwBufferLength = chunk;
        hHdr->dwBytesRecorded = 0;
        hHdr->dwUser = chunk;
        hHdr->dwFlags = 0;
        hHdr->dwLoops = 0;
        hHdr->lpNext = 0;
        hHdr->reserved = 0;

        status = waveOutPrepareHeader(audio_file_out, hHdr, sizeof(WAVEHDR));

        if (audioerror(status, AUDIOOUT, "out prepare header") == -1) {
            free(hHdr);
            free(hData);
            error(Eio);
        }

        status =
            waveOutWrite(audio_file_out, hHdr, sizeof(WAVEHDR));

        if (audioerror(status, AUDIOOUT, "out write data") == -1) {
            waveOutUnprepareHeader(audio_file_out, hHdr, sizeof(WAVEHDR));
            free(hHdr);
            free(hData);
            error(Eio);
        }

        WaitForSingleObject(outlock, INFINITE);
        out_buf_count += chunk;
        ReleaseMutex(outlock);

        total += chunk;

    }

    poperror();
    qunlock(&flag_lock);
    osmillisleep(1);	/* hack to get around thread scheduler */

    return count;
}
Exemple #2
0
/*
==================
FreeSound
==================
*/
void FreeSound (void)
{
	int		i;

	Com_Printf( "Shutting down sound system\n" );

	if ( pDS )
		DS_DestroyBuffers();

	if ( hWaveOut )
	{
		Com_Printf( "...resetting waveOut\n" );
		waveOutReset (hWaveOut);

		if (lpWaveHdr)
		{
			Com_Printf( "...unpreparing headers\n" );
			for (i=0 ; i< WAV_BUFFERS ; i++)
				waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
		}

		Com_Printf( "...closing waveOut\n" );
		waveOutClose (hWaveOut);

		if (hWaveHdr)
		{
			Com_Printf( "...freeing WAV header\n" );
			GlobalUnlock(hWaveHdr);
			GlobalFree(hWaveHdr);
		}

		if (hData)
		{
			Com_Printf( "...freeing WAV buffer\n" );
			GlobalUnlock(hData);
			GlobalFree(hData);
		}

	}

	if ( pDS )
	{
		Com_Printf( "...releasing DirectSound 8 object\n" );
#ifdef QDSNDCOMPILERHACK
		pDS->lpVtbl->Release(pDS);
#else
		pDS->Release();
#endif
	}

	if ( hInstDS )
	{
		Com_Printf( "...freeing dsound.dll\n" );
		FreeLibrary( hInstDS );
		hInstDS = NULL;
	}

	pDS = NULL;
	pDSBuf = NULL;
	pDSPBuf = NULL;
	hWaveOut = 0;
	hData = 0;
	hWaveHdr = 0;
	lpData = NULL;
	lpWaveHdr = NULL;
	dsound_init = 0;
	wav_init = 0;
}
Exemple #3
0
static void purge_output (void)
	{
	waveOutReset (dev);
	wait ();
	}           
Exemple #4
0
void CWaveOut::Reset()
{
    waveOutReset(m_hWave);
}
void WaveOut::ClearBuffers(){
    waveOutReset(this->waveHandle);
}
Exemple #6
0
void
cancelPcmOutput (PcmDevice *pcm) {
  waveOutReset(pcm->handle);
}
Exemple #7
0
static void WIN_PlayStop(void)
{
	if (hwaveout) waveOutReset(hwaveout);
	VC_PlayStop();
}
Exemple #8
0
unsigned int __stdcall SpkrThread(LPVOID Unused)
{
    int      i;
    DWORD    bufLen = ((N_SAMPLES * BITS_PER_SAMPLE) / 8);
    WAVEHDR* pWH;
    MMRESULT ret;
    int      played;
    OsMsg *pMsg = NULL;
    OsIntPtrMsg *pSpeakerMsg = NULL;
    BOOL     bGotMsg ;
    int      n;
    bool     bDone ;
    static bool sLastRingerEnabled = false;
    OsStatus res;
    static bool bRunning = false ;
    HWAVEOUT hOut = NULL;
    UINT    timerId=0;

    // Verify that only 1 instance of the MicThread is running
    if (bRunning) 
    {
       ResumeThread(hMicThread);
       return 1 ;
    }
    else
    {
       bRunning = true ;
    }
    ResumeThread(hMicThread);


#ifdef OHISTORY /* [ */
    WAVEHDR* lastWH[OHISTORY];
    int      lastInd[OHISTORY];
    int      last = 0;

    for (i=0;i<OHISTORY;i++) 
    {
        lastWH[i] = 0;
        lastInd[i] = 0;
    }

    memset(histOut, 0xff, sizeof(histOut));
    lastOut = 0;
#endif /* OHISTORY ] */
    
    // Initialize headers
    for (i=0; i<N_OUT_BUFFERS; i++) 
    {
        hOutHdr[i] = hOutBuf[i] = NULL;
        pOutHdr[i] = NULL;
    }
    
    if (openSpeakerDevices(pWH, hOut))
    {
        // NOT using a sound card
        // Set up a 10ms timer to call back to this routine
        timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC);
    }

    played = 0;   
    bDone = false ;
    while (!bDone)
    {
       bGotMsg = (gSpeakerStatusQueue->receive(pMsg) == OS_SUCCESS);
              
        // when switching devices, ringer to in-call we need to make 
        // sure any outstanding buffers are flushed
        if (sLastRingerEnabled != DmaTask::isRingerEnabled())
        {
            if (audioOutH)
            {
                ret = waveOutReset(audioOutH);
            }
            if (audioOutCallH)
            {
                ret = waveOutReset(audioOutCallH);
            }

            if (ret != MMSYSERR_NOERROR)
            {
                showWaveError("waveOutReset", ret, -1, __LINE__);
            }
            else
            {
                waitForDeviceResetCompletion();
            }
        }

        if (bGotMsg && pMsg) 
        {
           pSpeakerMsg = (OsIntPtrMsg*)pMsg;
           intptr_t msgType = pSpeakerMsg->getData1();
           intptr_t data2 = pSpeakerMsg->getData2();
           pSpeakerMsg->releaseMsg();
           pSpeakerMsg = NULL;
           pMsg = NULL;

            switch (msgType) 
            {
            case WM_ALT_HEARTBEAT:
                OsSysLog::add(FAC_MP, PRI_DEBUG,
                    "SpeakerThreadWnt invoking MpMediaTask::signalFrameStart from timer message");
                res = MpMediaTask::signalFrameStart();
                switch (res) 
                {
                   case OS_SUCCESS:
                        frameCount++;
                        break;
#ifdef DEBUG_WINDOZE /* [ */
                   case OS_LIMIT_REACHED:
                      // Should bump missed frame statistic
                      osPrintf(" Frame %d: OS_LIMIT_REACHED\n", frameCount);
                      break;
                   case OS_WAIT_TIMEOUT:
                      // Should bump missed frame statistic
                      osPrintf(" Frame %d: OS_WAIT_TIMEOUT\n", frameCount);
                      break;
                   case OS_ALREADY_SIGNALED:
                      // Should bump missed frame statistic
                      osPrintf(" Frame %d: OS_ALREADY_SIGNALED\n", frameCount);
                      break;
                   default:
                      osPrintf("Frame %d, signalFrameStart() returned %d\n",
                               frameCount, res);
                      break;
#else /* DEBUG_WINDOZE ] [ */
                   case OS_LIMIT_REACHED:
                   case OS_WAIT_TIMEOUT:
                   case OS_ALREADY_SIGNALED:
                   default:
                      // Should bump missed frame statistic
                      break;
#endif /* DEBUG_WINDOZE ] */
                }
                // Check for a changed speaker device
                if (DmaTask::isOutputDeviceChanged())
                {                    
                    DmaTask::clearOutputDeviceChanged() ;
                    closeSpeakerDevices() ;
                    if (audioOutH)
                    {
                        ret = waveOutReset(audioOutH);
                    }
                    if (audioOutCallH)
                    {
                        ret = waveOutReset(audioOutCallH);
                    }

                    if (ret != MMSYSERR_NOERROR)
                    {
                        showWaveError("waveOutReset", ret, -1, __LINE__);
                    }
                    else
                    {
                        waitForDeviceResetCompletion();
                    }

                    // Kill the hearbeat timer if it exists
                    if (timerId>0)
                        timeKillEvent(timerId);
                    if (openSpeakerDevices(pWH, hOut))
                    {
                        // Open failed - so start the heartbeat timer
                        timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC);                    
                    }
                    continue ;                    
                }
                break ;
            case WOM_DONE:
                pWH = (WAVEHDR *) data2;
                n = (pWH->dwUser) & USER_BUFFER_MASK;
#ifdef OHISTORY /* [ */
                lastWH[last] = pWH;
                lastInd[last] = n;
                last = (last + 1) % OHISTORY;

                if (N_OUT_BUFFERS == played) {
                    osPrintf("after first %d buffers:", played + 1);
                    osPrintf("\nCall Backs:");
                    for (i=0; i<OHISTORY; i++) {
                        osPrintf("%c%3d", (0 == (i % 20)) ? '\n' : ' ',
                        histOut[i]);
                    }
                    osPrintf("\n\nMessages:");
                    for (i=0; i<OHISTORY; i++) {
                        osPrintf("%c%3d", (0 == (i % 20)) ? '\n' : ' ',
                        lastInd[i]);
                    }
                    osPrintf("\n");
                }
#endif /* OHISTORY ] */
                
                if (DmaTask::isOutputDeviceChanged())
                {                    
                    DmaTask::clearOutputDeviceChanged() ;
                    closeSpeakerDevices() ;
                    if (openSpeakerDevices(pWH, hOut))
                    {
                        if (timerId>0)
                            timeKillEvent(timerId);
                        timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC);                    
                    }
                    continue ;                    
                }

                hOut = selectSpeakerDevice() ;
                if (hOut)
                {
                    ret = waveOutUnprepareHeader(hOut, pWH, sizeof(WAVEHDR));
                    if (ret != MMSYSERR_NOERROR)
                    {
                           showWaveError("waveOutUnprepareHeader", ret, played, __LINE__);
                    }
                    outPostUnprep(n, false);

                    pWH = outPrePrep(n, bufLen);

                    ret = waveOutPrepareHeader(hOut, pWH, sizeof(WAVEHDR));
                    if (ret != MMSYSERR_NOERROR)
                    {
                           showWaveError("waveOutPrepareHeader", ret, played, __LINE__);
                    }
                    ret = waveOutWrite(hOut, pWH, sizeof(WAVEHDR));
                    if (ret != MMSYSERR_NOERROR)
                    {
                           showWaveError("waveOutWrite", ret, played, __LINE__);
                    }
                    played++;
                }

                OsSysLog::add(FAC_MP, PRI_DEBUG,
                    "SpeakerThreadWnt invoking MpMediaTask::signalFrameStart from WOM_DONE message");
                res = MpMediaTask::signalFrameStart();

                switch (res) 
                {
#ifdef DEBUG_WINDOZE /* [ */
                case OS_SUCCESS:
                    frameCount++;
                    osPrintf(" Frame %d: OS_SUCCESSFUL\n", frameCount);
                    break;
                case OS_LIMIT_REACHED:
                    // Should bump missed frame statistic
                    osPrintf(" Frame %d: OS_LIMIT_REACHED\n", frameCount);
                   break;
                case OS_WAIT_TIMEOUT:
                    // Should bump missed frame statistic
                    osPrintf(" Frame %d: OS_WAIT_TIMEOUT\n", frameCount);
                    break;
                case OS_ALREADY_SIGNALED:
                    // Should bump missed frame statistic
                    osPrintf(" Frame %d: OS_ALREADY_SIGNALED\n", frameCount);
                    break;
                default:
                    osPrintf("Frame %d, signalFrameStart() returned %d\n",
                            frameCount, res);
                    break;
#else /* DEBUG_WINDOZE ] [ */
                case OS_SUCCESS:
                    frameCount++;
                    break;
                case OS_LIMIT_REACHED:
                case OS_WAIT_TIMEOUT:
                case OS_ALREADY_SIGNALED:
                default:
                    // Should bump missed frame statistic
                    break;
#endif /* DEBUG_WINDOZE ] */
                }
                break;
            case WOM_CLOSE:
                // Audio device was closed on us (doesn't happen as far as I
                // know)
                bDone = true ;
                break;
            default:                
                break;
            }
        } 
        else 
        {
            // Sky is falling, kick out so that we don't spin a high priority
            // thread.
            bDone = true ;
        }
      
        // record our last ringer state
        sLastRingerEnabled = DmaTask::isRingerEnabled();
    }

    // Stop heartbeat timer if it exist
    if (timerId>0)
        timeKillEvent(timerId);

    closeSpeakerDevices() ;

    bRunning = false ;

    return 0;
}
Exemple #9
0
static	DWORD	wodReset(WAVEMAPDATA* wom)
{
    TRACE("(%p)\n",wom);

    return waveOutReset(wom->u.out.hInnerWave);
}
Exemple #10
0
/***************************************************************************
 * 				MCIAVI_player			[internal]
 */
static	DWORD	MCIAVI_player(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
{
    DWORD		dwRet;
    LPWAVEHDR		waveHdr = NULL;
    unsigned		i, nHdr = 0;
    DWORD		numEvents = 1;
    HANDLE		events[2];
    double next_frame_us;

    EnterCriticalSection(&wma->cs);

    if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame)
    {
        dwRet = 0;
        goto mci_play_done;
    }

    events[0] = wma->hStopEvent;
    if (wma->lpWaveFormat) {
        if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0)
        {
            /* can't play audio */
            HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
            wma->lpWaveFormat = NULL;
        }
        else
        {
            /* fill the queue with as many wave headers as possible */
            MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
            events[1] = wma->hEvent;
            numEvents = 2;
        }
    }

    next_frame_us = currenttime_us();
    while (wma->dwStatus == MCI_MODE_PLAY)
    {
        HDC hDC;
        double tc, delta;
        DWORD ret;

        tc = currenttime_us();

        hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
        if (hDC)
        {
            while(next_frame_us <= tc && wma->dwCurrVideoFrame < wma->dwToVideoFrame) {
                double dur;
                dur = MCIAVI_PaintFrame(wma, hDC);
                ++wma->dwCurrVideoFrame;
                if(!dur)
                    break;
                next_frame_us += dur;
                TRACE("next_frame: %f\n", next_frame_us);
            }
            ReleaseDC(wma->hWndPaint, hDC);
        }
        if (wma->dwCurrVideoFrame >= wma->dwToVideoFrame)
        {
            if (!(dwFlags & MCI_DGV_PLAY_REPEAT))
                break;
            TRACE("repeat media as requested\n");
            wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
        }

        if (wma->lpWaveFormat)
            MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);

        tc = currenttime_us();
        if (tc < next_frame_us)
            delta = next_frame_us - tc;
        else
            delta = 0;

        LeaveCriticalSection(&wma->cs);
        ret = WaitForMultipleObjects(numEvents, events, FALSE, delta / 1000);
        EnterCriticalSection(&wma->cs);
        if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break;
    }

    if (wma->lpWaveFormat) {
        while (wma->dwEventCount != nHdr - 1)
        {
            LeaveCriticalSection(&wma->cs);
            Sleep(100);
            EnterCriticalSection(&wma->cs);
        }

        /* just to get rid of some race conditions between play, stop and pause */
        LeaveCriticalSection(&wma->cs);
        waveOutReset(wma->hWave);
        EnterCriticalSection(&wma->cs);

        for (i = 0; i < nHdr; i++)
            waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR));
    }

    dwRet = 0;

    if (wma->lpWaveFormat) {
        HeapFree(GetProcessHeap(), 0, waveHdr);

        if (wma->hWave) {
            LeaveCriticalSection(&wma->cs);
            waveOutClose(wma->hWave);
            EnterCriticalSection(&wma->cs);
            wma->hWave = 0;
        }
        CloseHandle(wma->hEvent);
    }

mci_play_done:
    wma->dwStatus = MCI_MODE_STOP;

    if (dwFlags & MCI_NOTIFY) {
        TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
        mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
                        wma->wDevID, MCI_NOTIFY_SUCCESSFUL);
    }
    LeaveCriticalSection(&wma->cs);
    return dwRet;
}
Exemple #11
0
void closeSpeakerDevices()
{
    MMRESULT ret;
    int i ;

    // Clean up ringer audio
    if (audioOutH)
    {
        ret = waveOutReset(audioOutH);
        if (ret != MMSYSERR_NOERROR)
        {
            showWaveError("waveOutReset", ret, -1, __LINE__);
        }
        else
        {
            waitForDeviceResetCompletion();
        }

        for (i=0; i<N_OUT_BUFFERS; i++) 
        {
            if (NULL != hOutHdr[i]) 
            {
                ret = waveOutUnprepareHeader(audioOutH, pOutHdr[i], sizeof(WAVEHDR));
                if (ret != MMSYSERR_NOERROR)
                {
                    showWaveError("waveOutUnprepareHeader", ret, i, __LINE__);
                }
                outPostUnprep(i, TRUE);
            }
        }
        
        ret = waveOutClose(audioOutH);
        if (ret != MMSYSERR_NOERROR)
        {
            showWaveError("waveOutClose", ret, -1, __LINE__);
        }
        audioOutH = NULL;

        waitForSpeakerStatusMessage(WOM_CLOSE);
    }

    // Clean up call audio
    if (audioOutCallH)
    {
        ret = waveOutReset(audioOutCallH);
        if (ret != MMSYSERR_NOERROR)
        {
            showWaveError("waveOutReset", ret, -1, __LINE__);
        }
        else
        {
            waitForDeviceResetCompletion();
        }

        for (i=0; i<N_OUT_BUFFERS; i++) 
        {
            if (NULL != hOutHdr[i]) 
            {
                ret = waveOutUnprepareHeader(audioOutCallH, pOutHdr[i], sizeof(WAVEHDR));
                if (ret != MMSYSERR_NOERROR)
                {
                    showWaveError("waveOutUnprepareHeader", ret, i, __LINE__);
                }
                outPostUnprep(i, true);
            }
        }

        ret = waveOutClose(audioOutCallH);
        if (ret != MMSYSERR_NOERROR)
        {
             showWaveError("waveOutClose", ret, -1, __LINE__);
        }
        audioOutCallH = NULL;

        waitForSpeakerStatusMessage(WOM_CLOSE);
    }
}
int AudioWaveOut::push_pcm_data(char* pbuf, int nlen)
{
	if (pbuf == NULL || nlen <= 0)
		return -1;
	if (!m_bInit && !bCanInPCM)
	{
		if (FailedCount++ >= 500)
		{
			FailedCount = 0;
			Log::writeMessage(LOG_RTSPSERV, 1, "waveout devicename %s 没有初始化成功 return!", WcharToAnsi(m_DeviceName.c_str()).c_str());
		}
		return -2;
	}
	MMRESULT mr = MMSYSERR_NOERROR;
	PWAVEPERIO hdr = m_wavequeue.front();
	if( hdr->hdr.dwFlags & WHDR_DONE || hdr->hdr.dwFlags == 0 )
	{
		mr = waveOutUnprepareHeader(m_outdev, &hdr->hdr, sizeof(WAVEHDR));
		if (mr != MMSYSERR_NOERROR)
			Log::writeMessage(LOG_RTSPSERV, 1, "waveOutUnprepareHeader ERROR devicename %s ", WcharToAnsi(m_DeviceName.c_str()).c_str());
	}
	else
	{
		Log::writeMessage(LOG_RTSPSERV, 1, "overrun reset devicename %s ", WcharToAnsi(m_DeviceName.c_str()).c_str());
		waveOutReset(m_outdev);
	}

	hdr->hdr.dwFlags = 0;
	hdr->hdr.dwUser = 0;
	if( nlen > MAX_SUPPORT_PCMPKG_LEN )
	{
		Log::writeMessage(LOG_RTSPSERV, 1, "PCM package len > MAX_SUPPORT_PCMPKG_LEN not play devicename %s ", WcharToAnsi(m_DeviceName.c_str()));
		return -5;
	}
	int dlen = nlen;
	if( m_bConver32t16 )
	{
		if( awresample( pbuf, nlen, (char*)hdr->buf, &dlen ) != 0 )
			Log::writeMessage(LOG_RTSPSERV, 1, "AudioWaveOut resample fail  devicename %s ", WcharToAnsi(m_DeviceName.c_str()));
	}
	else
		memcpy(hdr->buf, pbuf, nlen );
	hdr->hdr.lpData = (LPSTR)hdr->buf;
	hdr->hdr.dwBufferLength = dlen;

	mr = waveOutPrepareHeader(m_outdev, &hdr->hdr, sizeof(WAVEHDR));
	if (mr != MMSYSERR_NOERROR){
		if (FailedCount++ >= 100)
		{
			FailedCount = 0;
			Log::writeMessage(LOG_RTSPSERV, 1, "waveOutPrepareHeader fail devicename %s ", WcharToAnsi(m_DeviceName.c_str()).c_str());
			Uninitialize();
			Initialize(const_cast<TCHAR*>(m_DeviceName.c_str()), iChannels, iSamplerate, iSampleperbits);
		}
		return -3;
	}
	mr = waveOutWrite(m_outdev, &hdr->hdr, sizeof(WAVEHDR));
	if (mr != MMSYSERR_NOERROR){
		if (FailedCount++ >= 100)
		{
			FailedCount = 0;
			Log::writeMessage(LOG_RTSPSERV, 1, "waveOutWrite fail devicename %s ", WcharToAnsi(m_DeviceName.c_str()).c_str());
			Uninitialize();
			Initialize(const_cast<TCHAR*>(m_DeviceName.c_str()), iChannels, iSamplerate, iSampleperbits);
		}
		return -4;
	}
	m_wavequeue.pop();
	m_wavequeue.push(hdr);
	return 0;
}
Exemple #13
0
int main(int argc, char* argv[])
{
//    LPWSTR szFileName;//声音文件名
    MMCKINFO mmckinfoParent;
    MMCKINFO mmckinfoSubChunk;
    DWORD dwFmtSize;
    HMMIO m_hmmio;//音频文件句柄
    DWORD m_WaveLong;
    HPSTR lpData;//音频数据
    HANDLE m_hData=NULL;
    HANDLE m_hFormat;
    WAVEFORMATEX * lpFormat;
    DWORD m_dwDataOffset;
    DWORD m_dwDataSize;
    WAVEHDR pWaveOutHdr;
    WAVEOUTCAPS pwoc;
    HWAVEOUT hWaveOut;
    int SoundOffset=0;
    int SoundLong=0;
    int DevsNum;
    //打开波形文件
    if(!(m_hmmio=mmioOpen(argv[1],NULL,MMIO_READ|MMIO_ALLOCBUF)))
    {
    //File open Error
        printf("Failed to open the file.");//错误处理函数
        return false;
    }
    //检查打开文件是否是声音文件
    mmckinfoParent.fccType =mmioFOURCC('W','A','V','E');
    if(mmioDescend(m_hmmio,(LPMMCKINFO)&mmckinfoParent,NULL,MMIO_FINDRIFF))
    {
        printf("NOT WAVE FILE AND QUIT");
        return 0;
    }
    //寻找 'fmt' 块
    mmckinfoSubChunk.ckid =mmioFOURCC('f','m','t',' ');
    if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK))
    {
        printf("Can't find 'fmt' chunk");
        return 0;
    }
    //获得 'fmt '块的大小,申请内存
    dwFmtSize=mmckinfoSubChunk.cksize ;
    m_hFormat=LocalAlloc(LMEM_MOVEABLE,LOWORD(dwFmtSize));
    if(!m_hFormat)
    {
        printf("failed alloc memory");
        return 0;
    }
    lpFormat=(WAVEFORMATEX*)LocalLock(m_hFormat);
    if(!lpFormat)
    {
        printf("failed to lock the memory");
        return 0;
    }
    if((unsigned long)mmioRead(m_hmmio,(HPSTR)lpFormat,dwFmtSize)!=dwFmtSize)
    {
        printf("failed to read format chunk");
        return 0;
    }
    //离开 fmt 块
    mmioAscend(m_hmmio,&mmckinfoSubChunk,0);
    //寻找 'data' 块
    mmckinfoSubChunk.ckid=mmioFOURCC('d','a','t','a');
    if(mmioDescend(m_hmmio,&mmckinfoSubChunk,&mmckinfoParent,MMIO_FINDCHUNK))
    {
        printf("Can't find 'data' chunk");
        return 0;
    }
    //获得 'data'块的大小
    m_dwDataSize=mmckinfoSubChunk.cksize ;
    m_dwDataOffset =mmckinfoSubChunk.dwDataOffset ;
    if(m_dwDataSize==0L)
    {
        printf("no data in the 'data' chunk");
        return 0;
    }
    //为音频数据分配内存
    lpData=new char[m_dwDataSize];
    if(!lpData)
    {
        printf("\ncan not alloc mem");
        return 0;
    }
    if(mmioSeek(m_hmmio,m_dwDataOffset,SEEK_SET)<0)
    {
        printf("Failed to read the data chunk");
        return 0;
    }
//    m_WaveLong=mmioRead(m_hmmio,lpData,SoundLong);
    m_WaveLong=mmioRead(m_hmmio,lpData,m_dwDataSize);
   
    if(m_WaveLong<0)
    {
        printf("Failed to read the data chunk");
        return 0;
    }
    //检查音频设备,返回音频输出设备的性能
    if(waveOutGetDevCaps(WAVE_MAPPER,&pwoc,sizeof(WAVEOUTCAPS))!=0)
    {
        printf("Unable to allocate or lock memory");
        return 0;
    }

    //检查音频输出设备是否能播放指定的音频文件
    DevsNum = WAVE_MAPPER;
    if(waveOutOpen(&hWaveOut,DevsNum,lpFormat,NULL,NULL,CALLBACK_NULL)!=0)
    {
        printf("Failed to OPEN the wave out devices");
//        return 0;
    }
    //准备待播放的数据
    pWaveOutHdr.lpData =(HPSTR)lpData;
    pWaveOutHdr.dwBufferLength =m_WaveLong;
    pWaveOutHdr.dwFlags =0;
	pWaveOutHdr.dwLoops = 10;
    if(waveOutPrepareHeader(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0)
    {
        printf("Failed to prepare the wave data buffer");
        return 0;
    }
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutPrepareHeader]");

	pWaveOutHdr.dwFlags |= (WHDR_BEGINLOOP | WHDR_ENDLOOP);
    //播放音频数据文件
    if(waveOutWrite(hWaveOut,&pWaveOutHdr,sizeof(WAVEHDR))!=0)
    {
        printf("Failed to write the wave data buffer");
        return 0;
    }
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutWrite]");
    //关闭音频输出设备,释放内存
//     printf("\npress any key");
//     getchar();
	Sleep(20000);
	printFlags(pWaveOutHdr.dwFlags, "after [Sleep]");

	if(waveOutUnprepareHeader(hWaveOut, &pWaveOutHdr, sizeof(pWaveOutHdr)) != 0)
	{
		printf("Failed to unPrepare the wave data buffer");
        return 0;
	}
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutUnprepareHeader]");

    waveOutReset(hWaveOut);
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutReset]");

    waveOutClose(hWaveOut);
	printFlags(pWaveOutHdr.dwFlags, "after [waveOutClose]");

    LocalUnlock(m_hFormat);
    LocalFree(m_hFormat);
    delete [] lpData;

    return 0;
}
Exemple #14
0
/***************************************************************************
 * 				MCIAVI_mciPlay			[internal]
 */
static	DWORD	MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
{
    WINE_MCIAVI *wma;
    DWORD		frameTime;
    DWORD		dwRet;
    LPWAVEHDR		waveHdr = NULL;
    unsigned		i, nHdr = 0;
    DWORD		dwFromFrame, dwToFrame;
    DWORD		numEvents = 1;
    HANDLE		events[2];

    TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);

    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;

    wma = MCIAVI_mciGetOpenDev(wDevID);
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
    if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION;
    if (dwFlags & MCI_TEST)	return 0;

    EnterCriticalSection(&wma->cs);

    if (!wma->hFile)
    {
        LeaveCriticalSection(&wma->cs);
        return MCIERR_FILE_NOT_FOUND;
    }
    if (!wma->hWndPaint)
    {
        LeaveCriticalSection(&wma->cs);
        return MCIERR_NO_WINDOW;
    }

    LeaveCriticalSection(&wma->cs);

    if (!(dwFlags & MCI_WAIT))
        return MCIAVI_mciPlay_async(wma, dwFlags, lpParms);

    if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE))
        ShowWindow(wma->hWndPaint, SW_SHOWNA);

    EnterCriticalSection(&wma->cs);

    dwFromFrame = wma->dwCurrVideoFrame;
    dwToFrame = wma->dwPlayableVideoFrames - 1;

    if (lpParms && (dwFlags & MCI_FROM)) {
	dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom);
    }
    if (lpParms && (dwFlags & MCI_TO)) {
	dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
    }
    if (dwToFrame >= wma->dwPlayableVideoFrames)
	dwToFrame = wma->dwPlayableVideoFrames - 1;

    TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame);

    wma->dwCurrVideoFrame = dwFromFrame;
    wma->dwToVideoFrame = dwToFrame;

    /* if already playing exit */
    if (wma->dwStatus == MCI_MODE_PLAY)
    {
        LeaveCriticalSection(&wma->cs);
        SetEvent(wma->ack_event);
        return 0;
    }

    if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame)
    {
        dwRet = 0;
        SetEvent(wma->ack_event);
        goto mci_play_done;
    }

    wma->dwStatus = MCI_MODE_PLAY;
    /* signal the state change */
    SetEvent(wma->ack_event);

    if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN))
	FIXME("Unsupported flag %08x\n", dwFlags);

    /* time is in microseconds, we should convert it to milliseconds */
    frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000;

    events[0] = wma->hStopEvent;
    if (wma->lpWaveFormat) {
       if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0)
        {
            /* can't play audio */
            HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
            wma->lpWaveFormat = NULL;
        }
       else
       {
            /* fill the queue with as many wave headers as possible */
            MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
            events[1] = wma->hEvent;
            numEvents = 2;
       }
    }

    while (wma->dwStatus == MCI_MODE_PLAY)
    {
        HDC hDC;
        DWORD tc, delta;
        DWORD ret;

	tc = GetTickCount();

        hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
        if (hDC)
        {
            MCIAVI_PaintFrame(wma, hDC);
            ReleaseDC(wma->hWndPaint, hDC);
        }

        if (wma->lpWaveFormat)
	    MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);

	delta = GetTickCount() - tc;
	if (delta < frameTime)
            delta = frameTime - delta;
        else
            delta = 0;

        LeaveCriticalSection(&wma->cs);
        ret = WaitForMultipleObjects(numEvents, events, FALSE, delta);
        EnterCriticalSection(&wma->cs);
        if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break;

       if (wma->dwCurrVideoFrame < dwToFrame)
           wma->dwCurrVideoFrame++;
        else
            break;
    }

    if (wma->lpWaveFormat) {
       while (wma->dwEventCount != nHdr - 1)
        {
            LeaveCriticalSection(&wma->cs);
            Sleep(100);
            EnterCriticalSection(&wma->cs);
        }

	/* just to get rid of some race conditions between play, stop and pause */
	LeaveCriticalSection(&wma->cs);
	waveOutReset(wma->hWave);
	EnterCriticalSection(&wma->cs);

	for (i = 0; i < nHdr; i++)
	    waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR));
    }

    dwRet = 0;

    if (wma->lpWaveFormat) {
	HeapFree(GetProcessHeap(), 0, waveHdr);

	if (wma->hWave) {
	    LeaveCriticalSection(&wma->cs);
	    waveOutClose(wma->hWave);
	    EnterCriticalSection(&wma->cs);
	    wma->hWave = 0;
	}
	CloseHandle(wma->hEvent);
    }

mci_play_done:
    wma->dwStatus = MCI_MODE_STOP;

    if (lpParms && (dwFlags & MCI_NOTIFY)) {
	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
                       wDevID, MCI_NOTIFY_SUCCESSFUL);
    }
    LeaveCriticalSection(&wma->cs);
    return dwRet;
}
void closeWaveDevice()
{
    waveOutReset(hWaveOut);
    waveOutClose(hWaveOut);
}
Exemple #16
0
unsigned int WavePlayer::PlayThreadProcImpl()
{
	/// 定义为寄存器变量,因为它将会被高频率的使用,用于编译器优化
	register    ThreadMsg       tmsg = TMSG_ALIVE;

	/// 线程循环
	while (tmsg)
	{
		// 每次循环后,交出CPU控制权,放在此处,因为下面有continue语句
		Sleep(10);

		/// 首先检查线程消息
		EnterCriticalSection(&m_cs);
		tmsg = m_msgPlayThread;
		LeaveCriticalSection(&m_cs);
		// 线程要结束,退出线程循环
		if (!tmsg)   break;

		// 如果设备为空,表示还没有打开设备,需要打开设备
		if (m_hWaveoutDev == NULL)
		{
			EnterCriticalSection(&m_cs);
			MMRESULT mmres = waveOutOpen(&m_hWaveoutDev, WAVE_MAPPER, &m_waveData.wfmtx, (DWORD_PTR)WaveOutProc, (DWORD_PTR)this, CALLBACK_FUNCTION);
			LeaveCriticalSection(&m_cs);
			if (mmres != MMSYSERR_NOERROR)
			{
				// failed, try again.
				continue;
			}
		}

		// 检查空闲缓存块
		EnterCriticalSection(&m_cs);
		int free = m_wBlock.wfreeblock;
		LeaveCriticalSection(&m_cs);

		// 如果没有空闲的缓存了,等待...
		if (free < BP_TURN)
		{
			continue;
		}

		/////////////////////////////////////////////////////////////////////////
		/////////////////////////////////////////////////////////////////////////
		///                       < 播放主循环 >                              ///
		/////////////////////////////////////////////////////////////////////////
		/////////////////////////////////////////////////////////////////////////

		WAVEHDR     *current = NULL;

		/// BP_TURN为每次写入播放队列的块数
		for (unsigned int m = 0; m < BP_TURN; m++)
		{
			/// 当前空闲播放缓存块
			current = &m_wBlock.pWaveHdr[m_wBlock.wcurrblock];

			// 首先需要检查有没有被Unprepare掉
			if (current->dwFlags & WHDR_PREPARED)
			{
				waveOutUnprepareHeader(m_hWaveoutDev, current, sizeof(WAVEHDR));
			}

			/// 计算剩余需要播放的数据
			EnterCriticalSection(&m_cs);
			unsigned long left = m_waveData.dwSize - m_wBlock.wpos;
			unsigned int bDecodeFinished = m_waveData.bDecodeFinished;
			LeaveCriticalSection(&m_cs);
			unsigned long chunk = 0;

			if (left >= BLOCK_SIZE)
			{
				chunk = BLOCK_SIZE;
			}
			else if (!bDecodeFinished)
			{
				// 如果解码还没有结束,现有的数据量有不足以填满一个缓存块,先不写入缓存
				break;
			}
			else if (left && left < BLOCK_SIZE)
			{
				chunk = left;
			}
			else
			{
				//////////////////////////////////////////////////////////////////////
				///                 < 播放完成>                                    ///
				//////////////////////////////////////////////////////////////////////

				/// 获取空闲缓存块数量
				EnterCriticalSection(&m_cs);
				int free = m_wBlock.wfreeblock;
				LeaveCriticalSection(&m_cs);

				/// 当所有的缓存块都播放完了,才意味着播放真正完成
				if (free == BLOCK_COUNT)
				{
					/// Unprepare缓存块
					for (int j = 0; j < m_wBlock.wfreeblock; j++)
					{
						if (m_wBlock.pWaveHdr[j].dwFlags & WHDR_PREPARED)
						{
							waveOutUnprepareHeader(m_hWaveoutDev, &m_wBlock.pWaveHdr[j], sizeof(WAVEHDR));
						}
					}

					// 此时,才算真正的播放完成,关闭线程
					tmsg = TMSG_CLOSE;
					// 处理播放完成事件
					OnPlayFinished();
				}

				// 此break仅跳出该循环,没有跳出线程循环
				break;
			}

			/// prepare current wave data block header
			EnterCriticalSection(&m_cs);
			memcpy(current->lpData, &m_waveData.pData[m_wBlock.wpos], chunk);
			LeaveCriticalSection(&m_cs);

			current->dwBufferLength = chunk;   // sizeof block
			m_wBlock.wpos += chunk;   // update position

			/// prepare for playback
			waveOutPrepareHeader(m_hWaveoutDev, current, sizeof(WAVEHDR));

			/// push to the queue
			waveOutWrite(m_hWaveoutDev, current, sizeof(WAVEHDR));

			/// 减小空闲块计数
			EnterCriticalSection(&m_cs);
			m_wBlock.wfreeblock--;
			LeaveCriticalSection(&m_cs);

			/// 使当前空闲块指向下一个
			m_wBlock.wcurrblock++;
			m_wBlock.wcurrblock %= BLOCK_COUNT;
		}

	}/// thread

	///////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////
	///
	///            < force to close device which are still playing > 
	///////////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////////
	if (m_hWaveoutDev)
	{
		waveOutReset(m_hWaveoutDev);

		/// unprepare any blocks that are still prepared
		for (int j = 0; j < BLOCK_COUNT; j++)
		{
			if (m_wBlock.pWaveHdr[j].dwFlags & WHDR_PREPARED)
			{
				waveOutUnprepareHeader(m_hWaveoutDev, &m_wBlock.pWaveHdr[j], sizeof(WAVEHDR));
			}
		}

		waveOutClose(m_hWaveoutDev);
		m_hWaveoutDev = NULL;
	}

	return THREAD_EXIT;
}
Exemple #17
0
// --------------------------------
// Code
// --------------------------------
void audioPlay()
{
	if (g_AudioData.hWaveOut == NULL) // not initialized
		return;

	const AudioMetaData* pAudioMD = getAudioMetaData();
	if (pAudioMD == NULL || pAudioMD->DataSize() == 0 || !pAudioMD->IsDataNew())
		return;

	if (g_AudioData.bFlush)
	{
		printf("Audio is falling behind. Flushing all queue.\n");
		xnDumpFileWriteString(g_AudioData.SyncDump, "Flushing queue...\n");

		// mark not to check all dropped headers
		g_AudioData.nFirstToCheck = g_AudioData.nAudioNextBuffer;
		// flush all queued headers
		waveOutReset(g_AudioData.hWaveOut);

		g_AudioData.bFlush = false;
		return;
	}

	int nBufferSize = pAudioMD->DataSize();

	WAVEHDR* pHeader = &g_AudioData.pAudioBuffers[g_AudioData.nAudioNextBuffer];
	if ((pHeader->dwFlags & WHDR_DONE) == 0)
	{
		printf("No audio buffer is available!. Audio buffer will be lost!\n");
		return;
	}

	// first unprepare this header
	MMRESULT mmRes = waveOutUnprepareHeader(g_AudioData.hWaveOut, pHeader, sizeof(WAVEHDR));
	if (mmRes != MMSYSERR_NOERROR)
	{
		CHAR msg[250];
		waveOutGetErrorText(mmRes, msg, 250);
		printf("Failed unpreparing header: %s\n", msg);
	}

	int nMaxPlayedAudio = (int)(pAudioMD->SampleRate() / 1000.0 * pAudioMD->NumberOfChannels() * 2 * AUDIO_LATENCY_THRESHOLD);
	if (nBufferSize > nMaxPlayedAudio)
	{
		printf("Dropping %d bytes of audio to keep synch.\n", nBufferSize - nMaxPlayedAudio);
		nBufferSize = nMaxPlayedAudio;
	}

	const XnUInt8* pData = pAudioMD->Data();

	if (nBufferSize > g_AudioData.nBufferSize)
	{
		printf("Dropping %d bytes of audio to match buffer size.\n", nBufferSize - g_AudioData.nBufferSize);
		pData += (nBufferSize - g_AudioData.nBufferSize);
		nBufferSize = g_AudioData.nBufferSize;
	}

	pHeader->dwFlags = 0;
	xnOSMemCopy(pHeader->lpData, pData, nBufferSize);
	pHeader->dwBufferLength = nBufferSize;

	// prepare header
	mmRes = waveOutPrepareHeader(g_AudioData.hWaveOut, pHeader, sizeof(WAVEHDR));
	if (mmRes != MMSYSERR_NOERROR)
	{
		CHAR msg[250];
		waveOutGetErrorText(mmRes, msg, 250);
		printf("Unable to prepare header: %s\n", msg);
		return;
	}

	// queue header
	mmRes = waveOutWrite(g_AudioData.hWaveOut, pHeader, sizeof(WAVEHDR));
	if (mmRes != MMSYSERR_NOERROR)
	{
		CHAR msg[250];
		waveOutGetErrorText(mmRes, msg, 250);
		printf("Unable to queue header: %s\n", msg);
		return;
	}

	// place end-time as a timestamp
	g_AudioData.pAudioTimestamps[g_AudioData.nAudioNextBuffer] = (XnUInt64)(pAudioMD->Timestamp() + nBufferSize / (pAudioMD->BitsPerSample() / 8.0) / pAudioMD->NumberOfChannels() / (pAudioMD->SampleRate() / 1e6));

	xnDumpFileWriteString(g_AudioData.SyncDump, "Queued index %d with timestamp %llu (%u bytes, %f ms, end timestamp: %llu)\n", g_AudioData.nAudioNextBuffer, pAudioMD->Timestamp(), nBufferSize, nBufferSize / 2.0 / pAudioMD->NumberOfChannels() / (pAudioMD->SampleRate() / 1e3), g_AudioData.pAudioTimestamps[g_AudioData.nAudioNextBuffer]);

	g_AudioData.nAudioNextBuffer = (g_AudioData.nAudioNextBuffer + 1) % NUMBER_OF_AUDIO_BUFFERS;
}
void CDeviceWaveIO::AbortCloseAndRelease()
{
	if (mbStarted) {
		// Prevent more data from getting buffered
		mbBlocked_volatile = TRUE;

		// Wait until callback is finished - max wait time one second
		tbool bWait = true;
		tbool bTimeOut = false;
		DWORD dwTime0 = ::GetTickCount();
		while (bWait) {
			::Sleep(5);
			if (!mbInCallback_volatile)
				bWait = false;
			else {
				DWORD dwTime1 = ::GetTickCount();
				DWORD dwElapsed = (dwTime1 - dwTime0);
				if (dwElapsed > 1000) {
					// We've waited a whole second - abort now
					bWait = false;
					bTimeOut = true;
				}
			}
		}

		MMRESULT mmres = 0;

		if (!bTimeOut) {
			// Kill queued output (invokes waveOutProc_static with uMsg == WOM_DONE
			// - but new data won't get queued, because we've blocked)
			if (mbOutput) mmres = waveOutReset(mhandle_out);
			if (mbInput) mmres = waveInStop(mhandle_in);
			// Release the pair of buffers before we close device
			mmres = StopBuffers();
			// Close driver (invokes waveOutProc_static with uMsg == WOM_CLOSE)
			if (mbOutput) mmres = waveOutClose(mhandle_out);
			if (mbInput) mmres = waveInClose(mhandle_in);
		}
		// Remember we're closed
		mbStarted = FALSE;
	}

	for (tint32 iStructIx = 0; iStructIx < miRunningStructs; iStructIx++) {
		if (mapcOutputPCM[iStructIx]) {
			delete[] mapcOutputPCM[iStructIx];
			mapcOutputPCM[iStructIx] = NULL;
		}
		if (mapcInputPCM[iStructIx]) {
			delete[] mapcInputPCM[iStructIx];
			mapcInputPCM[iStructIx] = NULL;
		}
	}


	if (mppfInputs) {
		for (tint i = 0; i < WAVE_IO_MAX_INPUT_CHANNELS; i++) {
			delete[] mppfInputs[i];
		}
		delete[] mppfInputs;
		mppfInputs = NULL;
	}
	if (mppfOutputs) {
		for (tint i = 0; i < WAVE_IO_MAX_OUTPUT_CHANNELS; i++) {
			delete[] mppfOutputs[i];
		}
		delete[] mppfOutputs;
		mppfOutputs = NULL;
	}

	miRunningStructs = 0;
} // CDeviceWaveIO::AbortCloseAndRelease
bool SoundGenerator::Stop()
{
    return waveOutReset(m_hDeviceHandle) != MMSYSERR_NOERROR;
}
SoundLibrary2dWin32::~SoundLibrary2dWin32()
{
	waveOutReset(s_device);
	delete [] m_buffers;		m_buffers = NULL;
	waveOutClose(s_device);		s_device = NULL;
}
Exemple #21
0
static void
win32_play (get_audio_callback_t callback, AUDIO_OUT *audio_out, void *callback_data)
{	WIN32_AUDIO_OUT	*win32_out ;
	int		error ;

	if ((win32_out = (WIN32_AUDIO_OUT*) audio_out) == NULL)
	{	printf ("win32_play : AUDIO_OUT is NULL.\n") ;
		return ;
		} ;

	if (win32_out->magic != WIN32_MAGIC)
	{	printf ("win32_play : Bad magic number (%d %d).\n", win32_out->magic, WIN32_MAGIC) ;
		return ;
		} ;

	/* Set the callback function and callback data. */
	win32_out->callback = callback ;
	win32_out->callback_data = callback_data ;

	win32_out->whdr [0].lpData = (char*) win32_out->short_buffer ;
	win32_out->whdr [1].lpData = ((char*) win32_out->short_buffer) + sizeof (win32_out->short_buffer) / 2 ;

	win32_out->whdr [0].dwBufferLength = sizeof (win32_out->short_buffer) / 2 ;
	win32_out->whdr [1].dwBufferLength = sizeof (win32_out->short_buffer) / 2 ;

	win32_out->bufferlen = sizeof (win32_out->short_buffer) / 2 / sizeof (short) ;

	/* Prepare the WAVEHDRs */
	if ((error = waveOutPrepareHeader (win32_out->hwave, &(win32_out->whdr [0]), sizeof (WAVEHDR))))
	{	printf ("waveOutPrepareHeader [0] failed : %08X\n", error) ;
		waveOutClose (win32_out->hwave) ;
		return ;
		} ;

	if ((error = waveOutPrepareHeader (win32_out->hwave, &(win32_out->whdr [1]), sizeof (WAVEHDR))))
	{	printf ("waveOutPrepareHeader [1] failed : %08X\n", error) ;
		waveOutUnprepareHeader (win32_out->hwave, &(win32_out->whdr [0]), sizeof (WAVEHDR)) ;
		waveOutClose (win32_out->hwave) ;
		return ;
		} ;

	waveOutRestart (win32_out->hwave) ;

	/* Fake 2 calls to the callback function to queue up enough audio. */
	win32_audio_out_callback (0, MM_WOM_DONE, (DWORD) win32_out, 0, 0) ;
	win32_audio_out_callback (0, MM_WOM_DONE, (DWORD) win32_out, 0, 0) ;

	/* Wait for playback to finish. The callback notifies us when all
	** wave data has been played.
	*/
	WaitForSingleObject (win32_out->Event, INFINITE) ;

	waveOutPause (win32_out->hwave) ;
	waveOutReset (win32_out->hwave) ;

	waveOutUnprepareHeader (win32_out->hwave, &(win32_out->whdr [0]), sizeof (WAVEHDR)) ;
	waveOutUnprepareHeader (win32_out->hwave, &(win32_out->whdr [1]), sizeof (WAVEHDR)) ;

	waveOutClose (win32_out->hwave) ;
	win32_out->hwave = 0 ;

	return ;
} /* win32_play */
Exemple #22
0
void WaveOut::close()
{
	waveOutReset(hWaveOut);
	waveOutClose(hWaveOut);
	hWaveOut = NULL;
}
Exemple #23
0
BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static BOOL         bShutOff, bClosing ;
     static HWAVEOUT     hWaveOut ;
     static HWND         hwndScroll ;
     static int          iFreq = FREQ_INIT ;
     static PBYTE        pBuffer1, pBuffer2 ;
     static PWAVEHDR     pWaveHdr1, pWaveHdr2 ;
     static WAVEFORMATEX waveformat ;
     int                 iDummy ;
     
     switch (message)
     {
     case WM_INITDIALOG:
          hwndScroll = GetDlgItem (hwnd, IDC_SCROLL) ;
          SetScrollRange (hwndScroll, SB_CTL, FREQ_MIN, FREQ_MAX, FALSE) ;
          SetScrollPos   (hwndScroll, SB_CTL, FREQ_INIT, TRUE) ;
          SetDlgItemInt  (hwnd, IDC_TEXT, FREQ_INIT, FALSE) ;
          
          return TRUE ;
          
     case WM_HSCROLL:
          switch (LOWORD (wParam))
          {
          case SB_LINELEFT:   iFreq -=  1 ;  break ;
          case SB_LINERIGHT:  iFreq +=  1 ;  break ;
          case SB_PAGELEFT:   iFreq /=  2 ;  break ;
          case SB_PAGERIGHT:  iFreq *=  2 ;  break ;
               
          case SB_THUMBTRACK:
               iFreq = HIWORD (wParam) ;
               break ;
               
          case SB_TOP:
               GetScrollRange (hwndScroll, SB_CTL, &iFreq, &iDummy) ;
               break ;
               
          case SB_BOTTOM:
               GetScrollRange (hwndScroll, SB_CTL, &iDummy, &iFreq) ;
               break ;
          }
          
          iFreq = max (FREQ_MIN, min (FREQ_MAX, iFreq)) ;
          
          SetScrollPos (hwndScroll, SB_CTL, iFreq, TRUE) ;
          SetDlgItemInt (hwnd, IDC_TEXT, iFreq, FALSE) ;
          return TRUE ;
          
     case WM_COMMAND:
          switch (LOWORD (wParam))
          {
          case IDC_ONOFF:
                    // If turning on waveform, hWaveOut is NULL
               
               if (hWaveOut == NULL)
               {
                         // Allocate memory for 2 headers and 2 buffers

                    pWaveHdr1 = malloc (sizeof (WAVEHDR)) ;
                    pWaveHdr2 = malloc (sizeof (WAVEHDR)) ;
                    pBuffer1  = malloc (OUT_BUFFER_SIZE) ;
                    pBuffer2  = malloc (OUT_BUFFER_SIZE) ;

                    if (!pWaveHdr1 || !pWaveHdr2 || !pBuffer1 || !pBuffer2)
                    {
                         if (!pWaveHdr1) free (pWaveHdr1) ;
                         if (!pWaveHdr2) free (pWaveHdr2) ;
                         if (!pBuffer1)  free (pBuffer1) ;
                         if (!pBuffer2)  free (pBuffer2) ;

                         MessageBeep (MB_ICONEXCLAMATION) ;
                         MessageBox (hwnd, TEXT ("Error allocating memory!"),
                                     szAppName, MB_ICONEXCLAMATION | MB_OK) ;
                         return TRUE ;
                    }

                         // Variable to indicate Off button pressed

                    bShutOff = FALSE ;
                         
                         // Open waveform audio for output
                         
                    waveformat.wFormatTag      = WAVE_FORMAT_PCM ;
                    waveformat.nChannels       = 1 ;
                    waveformat.nSamplesPerSec  = SAMPLE_RATE ;
                    waveformat.nAvgBytesPerSec = SAMPLE_RATE ;
                    waveformat.nBlockAlign     = 1 ;
                    waveformat.wBitsPerSample  = 8 ;
                    waveformat.cbSize          = 0 ;
                         
                    if (waveOutOpen (&hWaveOut, WAVE_MAPPER, &waveformat,
                                     (DWORD) hwnd, 0, CALLBACK_WINDOW)
                              != MMSYSERR_NOERROR)
                    {
                         free (pWaveHdr1) ;
                         free (pWaveHdr2) ;
                         free (pBuffer1) ;
                         free (pBuffer2) ;

                         hWaveOut = NULL ;
                         MessageBeep (MB_ICONEXCLAMATION) ;
                         MessageBox (hwnd, 
                              TEXT ("Error opening waveform audio device!"),
                              szAppName, MB_ICONEXCLAMATION | MB_OK) ;
                         return TRUE ;
                    }

                         // Set up headers and prepare them

                    pWaveHdr1->lpData          = pBuffer1 ;
                    pWaveHdr1->dwBufferLength  = OUT_BUFFER_SIZE ;
                    pWaveHdr1->dwBytesRecorded = 0 ;
                    pWaveHdr1->dwUser          = 0 ;
                    pWaveHdr1->dwFlags         = 0 ;
                    pWaveHdr1->dwLoops         = 1 ;
                    pWaveHdr1->lpNext          = NULL ;
                    pWaveHdr1->reserved        = 0 ;
                    
                    waveOutPrepareHeader (hWaveOut, pWaveHdr1, 
                                          sizeof (WAVEHDR)) ;

                    pWaveHdr2->lpData          = pBuffer2 ;
                    pWaveHdr2->dwBufferLength  = OUT_BUFFER_SIZE ;
                    pWaveHdr2->dwBytesRecorded = 0 ;
                    pWaveHdr2->dwUser          = 0 ;
                    pWaveHdr2->dwFlags         = 0 ;
                    pWaveHdr2->dwLoops         = 1 ;
                    pWaveHdr2->lpNext          = NULL ;
                    pWaveHdr2->reserved        = 0 ;
                    
                    waveOutPrepareHeader (hWaveOut, pWaveHdr2,
                                          sizeof (WAVEHDR)) ;
               }
                    // If turning off waveform, reset waveform audio
               else
               {
                    bShutOff = TRUE ;
                    waveOutReset (hWaveOut) ;
               }
               return TRUE ;
          }
          break ;

               // Message generated from waveOutOpen call
               
     case MM_WOM_OPEN:
          SetDlgItemText (hwnd, IDC_ONOFF, TEXT ("Turn Off")) ;

               // Send two buffers to waveform output device
                    
          FillBuffer (pBuffer1, iFreq) ;
          waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
                    
          FillBuffer (pBuffer2, iFreq) ;
          waveOutWrite (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;
          return TRUE ;

               // Message generated when a buffer is finished
                    
     case MM_WOM_DONE:
          if (bShutOff)
          {
               waveOutClose (hWaveOut) ;
               return TRUE ;
          }

               // Fill and send out a new buffer

          FillBuffer (((PWAVEHDR) lParam)->lpData, iFreq) ;
          waveOutWrite (hWaveOut, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;
          return TRUE ;
          
     case MM_WOM_CLOSE:
          waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
          waveOutUnprepareHeader (hWaveOut, pWaveHdr2, sizeof (WAVEHDR)) ;

          free (pWaveHdr1) ;
          free (pWaveHdr2) ;
          free (pBuffer1) ;
          free (pBuffer2) ;

          hWaveOut = NULL ;
          SetDlgItemText (hwnd, IDC_ONOFF, TEXT ("Turn On")) ;
          
          if (bClosing)
               EndDialog (hwnd, 0) ;
          
          return TRUE ;
          
     case WM_SYSCOMMAND:
          switch (wParam)
          {
          case SC_CLOSE:
               if (hWaveOut != NULL)
               {
                    bShutOff = TRUE ;
                    bClosing = TRUE ;
                    
                    waveOutReset (hWaveOut) ;
               }
               else
                    EndDialog (hwnd, 0) ;
               
               return TRUE ;
          }
          break ;
     }
     return FALSE ;
}
Exemple #24
0
/*****************************************************************************
 * Open: open the audio device
 *****************************************************************************
 * This function opens and setups Win32 waveOut
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    aout_instance_t *p_aout = (aout_instance_t *)p_this;
    vlc_value_t val;
    int i;

    /* Allocate structure */
    p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );

    if( p_aout->output.p_sys == NULL )
    {
        msg_Err( p_aout, "out of memory" );
        return VLC_EGENERIC;
    }

    p_aout->output.pf_play = Play;
    p_aout->b_die = VLC_FALSE;

    if( var_Type( p_aout, "audio-device" ) == 0 )
    {
        Probe( p_aout );
    }

    if( var_Get( p_aout, "audio-device", &val ) < 0 )
    {
        /* Probe() has failed. */
        free( p_aout->output.p_sys );
        return VLC_EGENERIC;
    }

    var_Create( p_aout, "waveout-float32", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );

    /* Open the device */
    if( val.i_int == AOUT_VAR_SPDIF )
    {
        p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');

        if( OpenWaveOut( p_aout, VLC_FOURCC('s','p','d','i'),
                         p_aout->output.output.i_physical_channels,
                         aout_FormatNbChannels( &p_aout->output.output ),
                         p_aout->output.output.i_rate, VLC_FALSE )
            != VLC_SUCCESS )
        {
            msg_Err( p_aout, "cannot open waveout audio device" );
            free( p_aout->output.p_sys );
            return VLC_EGENERIC;
        }

        /* Calculate the frame size in bytes */
        p_aout->output.i_nb_samples = A52_FRAME_NB;
        p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
        p_aout->output.output.i_frame_length = A52_FRAME_NB;
        p_aout->output.p_sys->i_buffer_size =
            p_aout->output.output.i_bytes_per_frame;

        aout_VolumeNoneInit( p_aout );
    }
    else
    {
        if( val.i_int == AOUT_VAR_5_1 )
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
                   | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
                   | AOUT_CHAN_LFE;
        }
        else if( val.i_int == AOUT_VAR_2F2R )
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
                   | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
        }
        else if( val.i_int == AOUT_VAR_MONO )
        {
            p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
        }
        else
        {
            p_aout->output.output.i_physical_channels
                = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
        }

        if( OpenWaveOutPCM( p_aout, &p_aout->output.output.i_format,
                            p_aout->output.output.i_physical_channels,
                            aout_FormatNbChannels( &p_aout->output.output ),
                            p_aout->output.output.i_rate, VLC_FALSE )
            != VLC_SUCCESS )
        {
            msg_Err( p_aout, "cannot open waveout audio device" );
            free( p_aout->output.p_sys );
            return VLC_EGENERIC;
        }

        /* Calculate the frame size in bytes */
        p_aout->output.i_nb_samples = FRAME_SIZE;
        aout_FormatPrepare( &p_aout->output.output );
        p_aout->output.p_sys->i_buffer_size = FRAME_SIZE *
            p_aout->output.output.i_bytes_per_frame;

        aout_VolumeSoftInit( p_aout );
    }


    waveOutReset( p_aout->output.p_sys->h_waveout );

    /* Allocate silence buffer */
    p_aout->output.p_sys->p_silence_buffer =
        malloc( p_aout->output.p_sys->i_buffer_size );
    if( p_aout->output.p_sys->p_silence_buffer == NULL )
    {
        free( p_aout->output.p_sys );
        msg_Err( p_aout, "out of memory" );
        return 1;
    }

    /* Zero the buffer. WinCE doesn't have calloc(). */
    memset( p_aout->output.p_sys->p_silence_buffer, 0,
            p_aout->output.p_sys->i_buffer_size );

    /* Now we need to setup our waveOut play notification structure */
    p_aout->output.p_sys->p_notif =
        vlc_object_create( p_aout, sizeof(notification_thread_t) );
    p_aout->output.p_sys->p_notif->p_aout = p_aout;
    p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL );

    /* Then launch the notification thread */
    if( vlc_thread_create( p_aout->output.p_sys->p_notif,
                           "waveOut Notification Thread", WaveOutThread,
                           VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
    {
        msg_Err( p_aout, "cannot create WaveOutThread" );
    }

    /* We need to kick off the playback in order to have the callback properly
     * working */
    for( i = 0; i < FRAMES_NUM; i++ )
    {
        p_aout->output.p_sys->waveheader[i].dwFlags = WHDR_DONE;
        p_aout->output.p_sys->waveheader[i].dwUser = 0;
    }
    PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,
                 &p_aout->output.p_sys->waveheader[0], NULL );

    return 0;
}
Exemple #25
0
static BOOL MULTIMEDIA_PlaySound(const void* pszSound, HMODULE hmod, DWORD fdwSound, BOOL bUnicode)
{
    WINE_PLAYSOUND*     wps = NULL;

    TRACE("pszSound='%p' hmod=%p fdwSound=%08X\n",
	  pszSound, hmod, fdwSound);

    /* FIXME? I see no difference between SND_NOWAIT and SND_NOSTOP !
     * there could be one if several sounds can be played at once...
     */
    if ((fdwSound & (SND_NOWAIT | SND_NOSTOP)) && PlaySoundList != NULL)
	return FALSE;

    /* alloc internal structure, if we need to play something */
    if (pszSound && !(fdwSound & SND_PURGE))
    {
        if (!(wps = PlaySound_Alloc(pszSound, hmod, fdwSound, bUnicode)))
            return FALSE;
    }

    EnterCriticalSection(&WINMM_cs);
    /* since several threads can enter PlaySound in parallel, we're not
     * sure, at this point, that another thread didn't start a new playsound
     */
    while (PlaySoundList != NULL)
    {
        ResetEvent(psLastEvent);
        /* FIXME: doc says we have to stop all instances of pszSound if it's non
         * NULL... as of today, we stop all playing instances */
        SetEvent(psStopEvent);

        waveOutReset(PlaySoundList->hWave);
        LeaveCriticalSection(&WINMM_cs);
        WaitForSingleObject(psLastEvent, INFINITE);
        EnterCriticalSection(&WINMM_cs);

        ResetEvent(psStopEvent);
    }

    if (wps) wps->lpNext = PlaySoundList;
    PlaySoundList = wps;
    LeaveCriticalSection(&WINMM_cs);

    if (!pszSound || (fdwSound & SND_PURGE)) return TRUE;

    if (fdwSound & SND_ASYNC)
    {
        DWORD       id;
        HANDLE      handle;
        wps->bLoop = (fdwSound & SND_LOOP) ? TRUE : FALSE;
        if ((handle = CreateThread(NULL, 0, proc_PlaySound, wps, 0, &id)) != 0) {
            wps->hThread = handle;
            SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
            return TRUE;
        }
    }
    else return proc_PlaySound(wps);

    /* error cases */
    PlaySound_Free(wps);
    return FALSE;
}
void W32AudioDriver::StopDriver() {
	if (waveOut_) {
	   waveOutReset(waveOut_) ;
    }

} ;
static DWORD WINAPI proc_PlaySound(LPVOID arg)
{
    WINE_PLAYSOUND*     wps = arg;
    BOOL		bRet = FALSE;
    HMMIO		hmmio = 0;
    MMCKINFO		ckMainRIFF;
    MMCKINFO        	mmckInfo;
    LPWAVEFORMATEX      lpWaveFormat = NULL;
    HWAVEOUT		hWave = 0;
    LPWAVEHDR		waveHdr = NULL;
    INT			count, bufsize, left, index;
    struct playsound_data	s;
    void*               data;

    s.hEvent = 0;

    TRACE("SoundName=%s !\n", debugstr_w(wps->pszSound));

    /* if resource, grab it */
    if ((wps->fdwSound & SND_RESOURCE) == SND_RESOURCE) {
        static const WCHAR wszWave[] = {'W','A','V','E',0};
        HRSRC	hRes;
        HGLOBAL	hGlob;

        if ((hRes = FindResourceW(wps->hMod, wps->pszSound, wszWave)) == 0 ||
            (hGlob = LoadResource(wps->hMod, hRes)) == 0)
            goto errCleanUp;
        if ((data = LockResource(hGlob)) == NULL) {
            FreeResource(hGlob);
            goto errCleanUp;
        }
        FreeResource(hGlob);
    } else
        data = (void*)wps->pszSound;

    /* construct an MMIO stream (either in memory, or from a file */
    if (wps->fdwSound & SND_MEMORY)
    { /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */
	MMIOINFO	mminfo;

	memset(&mminfo, 0, sizeof(mminfo));
	mminfo.fccIOProc = FOURCC_MEM;
	mminfo.pchBuffer = data;
	mminfo.cchBuffer = -1; /* FIXME: when a resource, could grab real size */
	TRACE("Memory sound %p\n", data);
	hmmio = mmioOpenW(NULL, &mminfo, MMIO_READ);
    }
    if (!hmmio && wps->fdwSound & SND_ALIAS)
    {
        if ((wps->fdwSound & SND_ALIAS_ID) == SND_ALIAS_ID)
        {
            static const WCHAR  wszSystemAsterisk[] = {'S','y','s','t','e','m','A','s','t','e','r','i','s','k',0};
            static const WCHAR  wszSystemDefault[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t',0};
            static const WCHAR  wszSystemExclamation[] = {'S','y','s','t','e','m','E','x','c','l','a','m','a','t','i','o','n',0};
            static const WCHAR  wszSystemExit[] = {'S','y','s','t','e','m','E','x','i','t',0};
            static const WCHAR  wszSystemHand[] = {'S','y','s','t','e','m','H','a','n','d',0};
            static const WCHAR  wszSystemQuestion[] = {'S','y','s','t','e','m','Q','u','e','s','t','i','o','n',0};
            static const WCHAR  wszSystemStart[] = {'S','y','s','t','e','m','S','t','a','r','t',0};
            static const WCHAR  wszSystemWelcome[] = {'S','y','s','t','e','m','W','e','l','c','o','m','e',0};

            wps->fdwSound &= ~(SND_ALIAS_ID ^ SND_ALIAS);
            if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMASTERISK)
                wps->pszSound = wszSystemAsterisk;
            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMDEFAULT)
                wps->pszSound = wszSystemDefault;
            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXCLAMATION)
                wps->pszSound = wszSystemExclamation;
            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXIT)
                wps->pszSound = wszSystemExit;
            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMHAND)
                wps->pszSound = wszSystemHand;
            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMQUESTION)
                wps->pszSound = wszSystemQuestion;
            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMSTART)
                wps->pszSound = wszSystemStart;
            else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMWELCOME)
                wps->pszSound = wszSystemWelcome;
            else goto errCleanUp;
        }
        hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound);
        if (!hmmio)
        {
            wps->fdwSound &= ~SND_ALIAS;
            wps->fdwSound |= SND_FILENAME;
        }
    }
    if (!hmmio && wps->fdwSound & SND_FILENAME)
    {
        hmmio = get_mmioFromFile(wps->pszSound);
    }
    if (!(wps->fdwSound & (SND_FILENAME|SND_ALIAS|SND_MEMORY)))
    {
        if ((hmmio = get_mmioFromProfile(wps->fdwSound | SND_NODEFAULT, wps->pszSound)) == 0)
        {
            if ((hmmio = get_mmioFromFile(wps->pszSound)) == 0)
            {
                hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound);
            }
        }
    }
    if (hmmio == 0) goto errCleanUp;

    if (mmioDescend(hmmio, &ckMainRIFF, NULL, 0))
	goto errCleanUp;

    TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08X\n",
	  (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType, ckMainRIFF.cksize);

    if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
	(ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
	goto errCleanUp;

    mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
    if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
	goto errCleanUp;

    TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n",
	  (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize);

    lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
    if (!lpWaveFormat)
	goto errCleanUp;
    if (mmioRead(hmmio, (HPSTR)lpWaveFormat, mmckInfo.cksize) < sizeof(PCMWAVEFORMAT))
	goto errCleanUp;

    TRACE("wFormatTag=%04X !\n", 	lpWaveFormat->wFormatTag);
    TRACE("nChannels=%d\n", 		lpWaveFormat->nChannels);
    TRACE("nSamplesPerSec=%d\n", 	lpWaveFormat->nSamplesPerSec);
    TRACE("nAvgBytesPerSec=%d\n", 	lpWaveFormat->nAvgBytesPerSec);
    TRACE("nBlockAlign=%d\n", 		lpWaveFormat->nBlockAlign);
    TRACE("wBitsPerSample=%u !\n", 	lpWaveFormat->wBitsPerSample);

    /* move to end of 'fmt ' chunk */
    mmioAscend(hmmio, &mmckInfo, 0);

    mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
    if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
	goto errCleanUp;

    TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n",
	  (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize);

    s.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
    if (!s.hEvent || bPlaySoundStop)
	goto errCleanUp;

    if (waveOutOpen(&hWave, WAVE_MAPPER, lpWaveFormat, (DWORD_PTR)PlaySound_Callback,
		    (DWORD_PTR)&s, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
	goto errCleanUp;

    /* make it so that 3 buffers per second are needed */
    bufsize = (((lpWaveFormat->nAvgBytesPerSec / 3) - 1) / lpWaveFormat->nBlockAlign + 1) *
	lpWaveFormat->nBlockAlign;
    waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize);
    if (!waveHdr)
	goto errCleanUp;
    waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR);
    waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize;
    waveHdr[0].dwUser = waveHdr[1].dwUser = 0L;
    waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L;
    waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L;
    waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize;
    if (waveOutPrepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
	waveOutPrepareHeader(hWave, &waveHdr[1], sizeof(WAVEHDR))) {
	goto errCleanUp;
    }

    wps->hWave = hWave;
    s.dwEventCount = 1L; /* for first buffer */
    index = 0;

    do {
	left = mmckInfo.cksize;

	mmioSeek(hmmio, mmckInfo.dwDataOffset, SEEK_SET);
	while (left)
        {
	    if (bPlaySoundStop)
            {
		wps->bLoop = FALSE;
		break;
	    }
	    count = mmioRead(hmmio, waveHdr[index].lpData, min(bufsize, left));
	    if (count < 1) break;
	    left -= count;
	    waveHdr[index].dwBufferLength = count;
	    if (waveOutWrite(hWave, &waveHdr[index], sizeof(WAVEHDR)) == MMSYSERR_NOERROR) {
                index ^= 1;
                PlaySound_WaitDone(&s);
            }
            else {
		ERR("Aborting play loop, waveOutWrite error\n");
		wps->bLoop = FALSE;
		break;
	    }
	}
	bRet = TRUE;
    } while (wps->bLoop);

    PlaySound_WaitDone(&s); /* to balance first buffer */
    waveOutReset(hWave);

    waveOutUnprepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR));
    waveOutUnprepareHeader(hWave, &waveHdr[1], sizeof(WAVEHDR));

errCleanUp:
    TRACE("Done playing=%s => %s!\n", debugstr_w(wps->pszSound), bRet ? "ok" : "ko");
    HeapFree(GetProcessHeap(), 0, lpWaveFormat);
    if (hWave)
    {
        EnterCriticalSection(&WINMM_cs);
        /* the CS prevents a concurrent waveOutReset */
        wps->hWave = 0;
        LeaveCriticalSection(&WINMM_cs);
        while (waveOutClose(hWave) == WAVERR_STILLPLAYING)
            Sleep(100);
    }
    CloseHandle(s.hEvent);
    HeapFree(GetProcessHeap(), 0, waveHdr);
    if (hmmio) 		mmioClose(hmmio, 0);

    PlaySound_Free(wps);

    return bRet;
}
Exemple #28
0
/*
====================
SndSys_Shutdown

Stop the sound card, delete "snd_renderbuffer" and free its other resources
====================
*/
void SndSys_Shutdown (void)
{
#ifdef SUPPORTDIRECTX
	if (pDSBuf)
	{
		IDirectSoundBuffer_Stop(pDSBuf);
		IDirectSoundBuffer_Release(pDSBuf);
	}

	// only release primary buffer if it's not also the mixing buffer we just released
	if (pDSPBuf && (pDSBuf != pDSPBuf))
	{
		IDirectSoundBuffer_Release(pDSPBuf);
	}

	if (pDS)
	{
		IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL);
		IDirectSound_Release(pDS);
	}
#endif

	if (hWaveOut)
	{
		waveOutReset (hWaveOut);

		if (lpWaveHdr)
		{
			unsigned int i;

			for (i=0 ; i< WAV_BUFFERS ; i++)
				waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
		}

		waveOutClose (hWaveOut);

		if (hWaveHdr)
		{
			GlobalUnlock(hWaveHdr);
			GlobalFree(hWaveHdr);
		}

		if (hData)
		{
			GlobalUnlock(hData);
			GlobalFree(hData);
		}
	}

	if (snd_renderbuffer != NULL)
	{
		Mem_Free(snd_renderbuffer);
		snd_renderbuffer = NULL;
	}

#ifdef SUPPORTDIRECTX
	pDS = NULL;
	pDSBuf = NULL;
	pDSPBuf = NULL;
	dsound_init = false;
#endif
	hWaveOut = 0;
	hData = 0;
	hWaveHdr = 0;
	lpData = NULL;
	lpWaveHdr = NULL;
	wav_init = false;
}
Exemple #29
0
BOOL playTestTone()
{
	SHORT*               buffer;
	BOOL                 isChannelChecked;
#if 1
	WAVEFORMATEXTENSIBLE wfx;

	ZeroMemory(&wfx, sizeof(WAVEFORMATEXTENSIBLE));
	wfx.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
	wfx.Format.nChannels            = (WORD)currentChannelCount;
	wfx.Format.nSamplesPerSec       = SAMPLE_RATE;
	wfx.Format.wBitsPerSample       = 16;
	wfx.Format.nBlockAlign          = (wfx.Format.wBitsPerSample >> 3) * wfx.Format.nChannels;
	wfx.Format.nAvgBytesPerSec      = SAMPLE_RATE * (wfx.Format.wBitsPerSample >> 3) * wfx.Format.nChannels;
	wfx.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
	wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample ;
	wfx.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
#else
	WAVEFORMATEX         wfx;
	wfx.wFormatTag      = WAVE_FORMAT_PCM;
	wfx.wBitsPerSample  = 16;
	wfx.nChannels       = (WORD)currentChannelCount;
	wfx.nSamplesPerSec  = SAMPLE_RATE;
	wfx.nAvgBytesPerSec = SAMPLE_RATE * (wfx.wBitsPerSample >> 3) * wfx.nChannels;
	wfx.nBlockAlign     = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
	wfx.cbSize          = 0;
#endif

	isChannelChecked  = (SendMessage(GetDlgItem(hWndChild[0], IDC_LEFT), BM_GETCHECK, 0, 0) == BST_CHECKED);
	isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_RIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED);
	isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_BLEFT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 2);
	isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_BRIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 2);
	isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CENTER), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 4);
	isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_SUB), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 4);
	isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CLEFT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 6);
	isChannelChecked |= (SendMessage(GetDlgItem(hWndChild[0], IDC_CRIGHT), BM_GETCHECK, 0, 0) == BST_CHECKED) && (currentChannelCount > 6);

	if (!isChannelChecked)
		return FALSE;

	if (waveOutOpen(&hWave, findWaveDeviceID(), (WAVEFORMATEX*)&(wfx), 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) {
		PrintLastError("waveOutOpen()");
		return FALSE;
	}

	if (!generateTestSignal(SPEAKER_AMPLITUDE, currentChannelCount, SAMPLE_RATE, &buffer)) {
		return FALSE;
	}

	ZeroMemory(&pwh, sizeof(pwh));
	pwh.lpData         = (LPSTR)buffer;
	pwh.dwBufferLength = SAMPLE_RATE*sizeof(SHORT)*currentChannelCount;
	pwh.dwFlags        = WHDR_BEGINLOOP | WHDR_ENDLOOP;
	pwh.dwLoops        = 0xFFFFFFFF;
	if (waveOutPrepareHeader(hWave, &pwh, sizeof(pwh)) != MMSYSERR_NOERROR) {
		LocalFree(buffer);
		PrintLastError("waveOutPrepareHeader()");
		return FALSE;
	}

 	if (waveOutReset(hWave) != MMSYSERR_NOERROR) {
		LocalFree(buffer);
		PrintLastError("waveOutReset()");
		return FALSE;
	}
	if (waveOutWrite(hWave, &pwh, sizeof(WAVEHDR)) != MMSYSERR_NOERROR) {
		LocalFree(buffer);
		PrintLastError("waveOutWrite()");
		return FALSE;
	}

	return TRUE;
}
Exemple #30
0
BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static BOOL         bRecording, bPlaying, bReverse, bPaused,
                         bEnding, bTerminating ;
     static DWORD        dwDataLength, dwRepetitions = 1 ;
     static HWAVEIN      hWaveIn ;
     static HWAVEOUT     hWaveOut ;
     static PBYTE        pBuffer1, pBuffer2, pSaveBuffer, pNewBuffer ;
     static PWAVEHDR     pWaveHdr1, pWaveHdr2 ;
     static TCHAR        szOpenError[] = TEXT ("Error opening waveform audio!");
     static TCHAR        szMemError [] = TEXT ("Error allocating memory!") ;
     static WAVEFORMATEX waveform ;
     
     switch (message)
     {
     case WM_INITDIALOG:
               // Allocate memory for wave header
          
          pWaveHdr1 = malloc (sizeof (WAVEHDR)) ;
          pWaveHdr2 = malloc (sizeof (WAVEHDR)) ;
          
               // Allocate memory for save buffer
          
          pSaveBuffer = malloc (1) ;
          return TRUE ;
          
     case WM_COMMAND:
          switch (LOWORD (wParam))
          {
          case IDC_RECORD_BEG:
                    // Allocate buffer memory

               pBuffer1 = malloc (INP_BUFFER_SIZE) ;
               pBuffer2 = malloc (INP_BUFFER_SIZE) ;
               
               if (!pBuffer1 || !pBuffer2)
               {
                    if (pBuffer1) free (pBuffer1) ;
                    if (pBuffer2) free (pBuffer2) ;

                    MessageBeep (MB_ICONEXCLAMATION) ;
                    MessageBox (hwnd, szMemError, szAppName,
                                      MB_ICONEXCLAMATION | MB_OK) ;
                    return TRUE ;
               }
               
                    // Open waveform audio for input
               
               waveform.wFormatTag      = WAVE_FORMAT_PCM ;
               waveform.nChannels       = 1 ;
               waveform.nSamplesPerSec  = 11025 ;
               waveform.nAvgBytesPerSec = 11025 ;
               waveform.nBlockAlign     = 1 ;
               waveform.wBitsPerSample  = 8 ;
               waveform.cbSize          = 0 ;
               
               if (waveInOpen (&hWaveIn, WAVE_MAPPER, &waveform, 
                               (DWORD) hwnd, 0, CALLBACK_WINDOW))
               {
                    free (pBuffer1) ;
                    free (pBuffer2) ;
                    MessageBeep (MB_ICONEXCLAMATION) ;
                    MessageBox (hwnd, szOpenError, szAppName,
                                      MB_ICONEXCLAMATION | MB_OK) ;
               }
                    // Set up headers and prepare them
               
               pWaveHdr1->lpData          = pBuffer1 ;
               pWaveHdr1->dwBufferLength  = INP_BUFFER_SIZE ;
               pWaveHdr1->dwBytesRecorded = 0 ;
               pWaveHdr1->dwUser          = 0 ;
               pWaveHdr1->dwFlags         = 0 ;
               pWaveHdr1->dwLoops         = 1 ;
               pWaveHdr1->lpNext          = NULL ;
               pWaveHdr1->reserved        = 0 ;

               waveInPrepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
          
               pWaveHdr2->lpData          = pBuffer2 ;
               pWaveHdr2->dwBufferLength  = INP_BUFFER_SIZE ;
               pWaveHdr2->dwBytesRecorded = 0 ;
               pWaveHdr2->dwUser          = 0 ;
               pWaveHdr2->dwFlags         = 0 ;
               pWaveHdr2->dwLoops         = 1 ;
               pWaveHdr2->lpNext          = NULL ;
               pWaveHdr2->reserved        = 0 ;
          
               waveInPrepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
               return TRUE ;
               
          case IDC_RECORD_END:
                    // Reset input to return last buffer
               
               bEnding = TRUE ;
               waveInReset (hWaveIn) ;
               return TRUE ;
               
          case IDC_PLAY_BEG:
                    // Open waveform audio for output
               
               waveform.wFormatTag      = WAVE_FORMAT_PCM ;
               waveform.nChannels       = 1 ;
               waveform.nSamplesPerSec  = 11025 ;
               waveform.nAvgBytesPerSec = 11025 ;
               waveform.nBlockAlign     = 1 ;
               waveform.wBitsPerSample  = 8 ;
               waveform.cbSize          = 0 ;
               
               if (waveOutOpen (&hWaveOut, WAVE_MAPPER, &waveform, 
                                (DWORD) hwnd, 0, CALLBACK_WINDOW))
               {
                    MessageBeep (MB_ICONEXCLAMATION) ;
                    MessageBox (hwnd, szOpenError, szAppName,
                         MB_ICONEXCLAMATION | MB_OK) ;
               }
               return TRUE ;
               
          case IDC_PLAY_PAUSE:
                    // Pause or restart output
               
               if (!bPaused)
               {
                    waveOutPause (hWaveOut) ;
                    SetDlgItemText (hwnd, IDC_PLAY_PAUSE, TEXT ("Resume")) ;
                    bPaused = TRUE ;
               }
               else
               {
                    waveOutRestart (hWaveOut) ;
                    SetDlgItemText (hwnd, IDC_PLAY_PAUSE, TEXT ("Pause")) ;
                    bPaused = FALSE ;
               }
               return TRUE ;
               
          case IDC_PLAY_END:
                    // Reset output for close preparation
               
               bEnding = TRUE ;
               waveOutReset (hWaveOut) ;
               return TRUE ;
               
          case IDC_PLAY_REV:
                    // Reverse save buffer and play
               
               bReverse = TRUE ;
               ReverseMemory (pSaveBuffer, dwDataLength) ;
               
               SendMessage (hwnd, WM_COMMAND, IDC_PLAY_BEG, 0) ;
               return TRUE ;
               
          case IDC_PLAY_REP:
                    // Set infinite repetitions and play
               
               dwRepetitions = -1 ;
               SendMessage (hwnd, WM_COMMAND, IDC_PLAY_BEG, 0) ;
               return TRUE ;
               
          case IDC_PLAY_SPEED:
                    // Open waveform audio for fast output
               
               waveform.wFormatTag      = WAVE_FORMAT_PCM ;
               waveform.nChannels       = 1 ;
               waveform.nSamplesPerSec  = 22050 ;
               waveform.nAvgBytesPerSec = 22050 ;
               waveform.nBlockAlign     = 1 ;
               waveform.wBitsPerSample  = 8 ;
               waveform.cbSize          = 0 ;
               
               if (waveOutOpen (&hWaveOut, 0, &waveform, (DWORD) hwnd, 0,
                                           CALLBACK_WINDOW))
               {
                    MessageBeep (MB_ICONEXCLAMATION) ;
                    MessageBox (hwnd, szOpenError, szAppName,
                                      MB_ICONEXCLAMATION | MB_OK) ;
               }
               return TRUE ;
          }
          break ;
               
     case MM_WIM_OPEN:
               // Shrink down the save buffer
          
          pSaveBuffer = realloc (pSaveBuffer, 1) ;
          
               // Enable and disable Buttons
          
          EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), TRUE)  ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG),   FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END),   FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REV),   FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REP),   FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_SPEED), FALSE) ;
          SetFocus (GetDlgItem (hwnd, IDC_RECORD_END)) ;

               // Add the buffers
          
          waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
          waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
          
               // Begin sampling
          
          bRecording = TRUE ;
          bEnding = FALSE ;
          dwDataLength = 0 ;
          waveInStart (hWaveIn) ;
          return TRUE ;
          
     case MM_WIM_DATA:
         
               // Reallocate save buffer memory
          
          pNewBuffer = realloc (pSaveBuffer, dwDataLength +
                                   ((PWAVEHDR) lParam)->dwBytesRecorded) ;
          
          if (pNewBuffer == NULL)
          {
               waveInClose (hWaveIn) ;
               MessageBeep (MB_ICONEXCLAMATION) ;
               MessageBox (hwnd, szMemError, szAppName,
                                 MB_ICONEXCLAMATION | MB_OK) ;
               return TRUE ;
          }
          
          pSaveBuffer = pNewBuffer ;
          CopyMemory (pSaveBuffer + dwDataLength, ((PWAVEHDR) lParam)->lpData,
                         ((PWAVEHDR) lParam)->dwBytesRecorded) ;
          
          dwDataLength += ((PWAVEHDR) lParam)->dwBytesRecorded ;
          
          if (bEnding)
          {
               waveInClose (hWaveIn) ;
               return TRUE ;
          }
          
               // Send out a new buffer
          
          waveInAddBuffer (hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;
          return TRUE ;
          
     case MM_WIM_CLOSE:
               // Free the buffer memory

          waveInUnprepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
          waveInUnprepareHeader (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;

          free (pBuffer1) ;
          free (pBuffer2) ;
          
               // Enable and disable buttons
          
          EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), TRUE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), FALSE) ;
          SetFocus (GetDlgItem (hwnd, IDC_RECORD_BEG)) ;
          
          if (dwDataLength > 0)
          {
               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG),   TRUE)  ;
               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE) ;
               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END),   FALSE) ;
               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REP),   TRUE)  ;
               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REV),   TRUE)  ;
               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_SPEED), TRUE)  ;
               SetFocus (GetDlgItem (hwnd, IDC_PLAY_BEG)) ;
          }
          bRecording = FALSE ;
          
          if (bTerminating)
               SendMessage (hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L) ;
          
          return TRUE ;
          
     case MM_WOM_OPEN:
               // Enable and disable buttons
          
          EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG),   FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), TRUE)  ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END),   TRUE)  ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REP),   FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REV),   FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_SPEED), FALSE) ;
          SetFocus (GetDlgItem (hwnd, IDC_PLAY_END)) ;
          
               // Set up header
          
          pWaveHdr1->lpData          = pSaveBuffer ;
          pWaveHdr1->dwBufferLength  = dwDataLength ;
          pWaveHdr1->dwBytesRecorded = 0 ;
          pWaveHdr1->dwUser          = 0 ;
          pWaveHdr1->dwFlags         = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
          pWaveHdr1->dwLoops         = dwRepetitions ;
          pWaveHdr1->lpNext          = NULL ;
          pWaveHdr1->reserved        = 0 ;
          
               // Prepare and write
          
          waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
          waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
          
          bEnding = FALSE ;
          bPlaying = TRUE ;
          return TRUE ;
          
     case MM_WOM_DONE:
          waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
          waveOutClose (hWaveOut) ;
          return TRUE ;
          
     case MM_WOM_CLOSE:
               // Enable and disable buttons
          
          EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), TRUE)  ;
          EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), TRUE)  ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG),   TRUE)  ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END),   FALSE) ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REV),   TRUE)  ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_REP),   TRUE)  ;
          EnableWindow (GetDlgItem (hwnd, IDC_PLAY_SPEED), TRUE)  ;
          SetFocus (GetDlgItem (hwnd, IDC_PLAY_BEG)) ;
          
          SetDlgItemText (hwnd, IDC_PLAY_PAUSE, TEXT ("Pause")) ;
          bPaused = FALSE ;
          dwRepetitions = 1 ;
          bPlaying = FALSE ;
          
          if (bReverse)
          {
               ReverseMemory (pSaveBuffer, dwDataLength) ;
               bReverse = FALSE ;
          }
          
          if (bTerminating)
               SendMessage (hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L) ;
          
          return TRUE ;
          
     case WM_SYSCOMMAND:
          switch (LOWORD (wParam))
          {
          case SC_CLOSE:
               if (bRecording)
               {
                    bTerminating = TRUE ;
                    bEnding = TRUE ;
                    waveInReset (hWaveIn) ;
                    return TRUE ;
               }
               
               if (bPlaying)
               {
                    bTerminating = TRUE ;
                    bEnding = TRUE ;
                    waveOutReset (hWaveOut) ;
                    return TRUE ;
               }
               
               free (pWaveHdr1) ;
               free (pWaveHdr2) ;
               free (pSaveBuffer) ;
               EndDialog (hwnd, 0) ;
               return TRUE ;
          }
          break ;
     }
     return FALSE ;
}