Ejemplo n.º 1
0
static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
{
    ALbyte *BufferData = NULL;
    DWORD ulCapturedDataSize;
    WinMMData *pData = NULL;
    UINT lDeviceID = 0;
    ALint lBufferSize;
    MMRESULT res;
    ALuint i;

    if(!CaptureDeviceList)
        ProbeCaptureDevices();

    // Find the Device ID matching the deviceName if valid
    for(i = 0;i < NumCaptureDevices;i++)
    {
        if(CaptureDeviceList[i] &&
           (!deviceName || strcmp(deviceName, CaptureDeviceList[i]) == 0))
        {
            lDeviceID = i;
            break;
        }
    }
    if(i == NumCaptureDevices)
        return ALC_INVALID_VALUE;

    switch(pDevice->FmtChans)
    {
        case DevFmtMono:
        case DevFmtStereo:
            break;

        case DevFmtQuad:
        case DevFmtX51:
        case DevFmtX51Side:
        case DevFmtX61:
        case DevFmtX71:
            return ALC_INVALID_ENUM;
    }

    switch(pDevice->FmtType)
    {
        case DevFmtUByte:
        case DevFmtShort:
        case DevFmtInt:
        case DevFmtFloat:
            break;

        case DevFmtByte:
        case DevFmtUShort:
        case DevFmtUInt:
            return ALC_INVALID_ENUM;
    }

    pData = calloc(1, sizeof(*pData));
    if(!pData)
        return ALC_OUT_OF_MEMORY;
    pDevice->ExtraData = pData;

    memset(&pData->wfexFormat, 0, sizeof(WAVEFORMATEX));
    pData->wfexFormat.wFormatTag = ((pDevice->FmtType == DevFmtFloat) ?
                                    WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
    pData->wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
    pData->wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
    pData->wfexFormat.nBlockAlign = pData->wfexFormat.wBitsPerSample *
                                    pData->wfexFormat.nChannels / 8;
    pData->wfexFormat.nSamplesPerSec = pDevice->Frequency;
    pData->wfexFormat.nAvgBytesPerSec = pData->wfexFormat.nSamplesPerSec *
                                        pData->wfexFormat.nBlockAlign;
    pData->wfexFormat.cbSize = 0;

    if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &pData->wfexFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
    {
        ERR("waveInOpen failed: %u\n", res);
        goto failure;
    }

    pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if(pData->hWaveThreadEvent == NULL)
    {
        ERR("CreateEvent failed: %lu\n", GetLastError());
        goto failure;
    }

    // Allocate circular memory buffer for the captured audio
    ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates;

    // Make sure circular buffer is at least 100ms in size
    if(ulCapturedDataSize < (pData->wfexFormat.nSamplesPerSec / 10))
        ulCapturedDataSize = pData->wfexFormat.nSamplesPerSec / 10;

    pData->pRing = CreateRingBuffer(pData->wfexFormat.nBlockAlign, ulCapturedDataSize);
    if(!pData->pRing)
        goto failure;

    pData->lWaveBuffersCommitted = 0;

    // Create 4 Buffers of 50ms each
    lBufferSize = pData->wfexFormat.nAvgBytesPerSec / 20;
    lBufferSize -= (lBufferSize % pData->wfexFormat.nBlockAlign);

    BufferData = calloc(4, lBufferSize);
    if(!BufferData)
        goto failure;

    for(i = 0;i < 4;i++)
    {
        memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
        pData->WaveBuffer[i].dwBufferLength = lBufferSize;
        pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
                                       (pData->WaveBuffer[i-1].lpData +
                                        pData->WaveBuffer[i-1].dwBufferLength));
        pData->WaveBuffer[i].dwFlags = 0;
        pData->WaveBuffer[i].dwLoops = 0;
        waveInPrepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
        waveInAddBuffer(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
        InterlockedIncrement(&pData->lWaveBuffersCommitted);
    }

    pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveThreadID);
    if (pData->hWaveThread == NULL)
        goto failure;

    pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]);
    return ALC_NO_ERROR;

failure:
    if(pData->hWaveThread)
        CloseHandle(pData->hWaveThread);

    if(BufferData)
    {
        for(i = 0;i < 4;i++)
            waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
        free(BufferData);
    }

    if(pData->pRing)
        DestroyRingBuffer(pData->pRing);

    if(pData->hWaveThreadEvent)
        CloseHandle(pData->hWaveThreadEvent);

    if(pData->hWaveHandle.In)
        waveInClose(pData->hWaveHandle.In);

    free(pData);
    pDevice->ExtraData = NULL;
    return ALC_INVALID_VALUE;
}
Ejemplo n.º 2
0
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 it's "
              "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);
}
Ejemplo n.º 3
0
int32 ad_read (ad_rec_t *r, int16 *buf, int32 max)
{
    int32 t, st, len;
    LPWAVEHDR whdr;
    int16 *sysbufp;

    if (! r->opened)
	return AD_ERR_NOT_OPEN;

    /* Check if all recorded data exhausted */
    if ((! r->recording) && (r->curbuf == r->lastbuf) && (r->curlen == 0))
	return AD_EOF;

    len = 0;
    while (max > 0) {
	/* Look for next buffer with recording data */
	if (r->curlen == 0) {
	    /* No current buffer with data; get next buffer in sequence if available */
	    t = r->curbuf+1;
	    if (t >= r->n_buf)
		t = 0;
	    
	    if (! (r->wi_buf[t].p_whdr->dwFlags & WHDR_DONE))
		return len;

	    r->curbuf = t;
	    r->curlen = r->wi_buf[t].p_whdr->dwBytesRecorded >> 1;
	    r->curoff = 0;
	}

	/* Copy data from curbuf to buf */
	whdr = r->wi_buf[r->curbuf].p_whdr;
	t = (max < r->curlen) ? max : r->curlen;	/* #Samples to copy */

	if (t > 0) {
	    sysbufp = (int16 *) (whdr->lpData);
	    memcpy (buf, sysbufp + r->curoff, t * sizeof(int16));

	    buf += t;
	    max -= t;
	    r->curoff += t;
	    r->curlen -= t;
	    len += t;
	}

	/* If curbuf empty recycle it to system if still recording */
	if (r->curlen == 0) {
	    if (r->recording) {
		/* Return empty buffer to system */
		st = waveInUnprepareHeader (r->h_wavein, whdr, sizeof(WAVEHDR));
		if (st != 0) {
		    wavein_error("waveInUnprepareHeader", st);
		    return AD_ERR_WAVE;
		}

		if (wavein_enqueue_buf (r->h_wavein, whdr) < 0)
		    return AD_ERR_WAVE;

	    } else if (r->curbuf == r->lastbuf) {
		return len;
	    }
	}
    }
Ejemplo n.º 4
0
BOOL CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
	static BOOL         bRecording, bPlaying, bPaused, bEnding, bTerminating;
	static DWORD        dwRepetitions = 1;
	static HWAVEIN      hWaveIn;
	static HWAVEOUT     hWaveOut;
	static PBYTE        pBuffer1, pBuffer2, pNewBuffer;
	static PWAVEHDR     pWaveHdr1, pWaveHdr2;
	static TCHAR        szOpenError[] = TEXT("Error opening waveform audio!");
	static TCHAR        szMemError[] = TEXT("Error allocating memory!");

	switch (message) {
	case WM_INITDIALOG:
		// Allocate memory for wave header

		pWaveHdr1 = malloc(sizeof(WAVEHDR));
		pWaveHdr2 = malloc(sizeof(WAVEHDR));

		wndHwnd = hwnd;

		// 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.nAvgBytesPerSec = waveform.nBlockAlign * waveform.nSamplesPerSec;
			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.nAvgBytesPerSec = waveform.nBlockAlign * waveform.nSamplesPerSec;
			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;
		}
		break;

	case MM_WIM_OPEN:
		// Shrink down the save buffer

		pSaveBuffer = realloc(pSaveBuffer, 1);

		// 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);

		bRecording = FALSE;

		if (bTerminating)
			SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);

		return TRUE;

	case MM_WOM_OPEN:

		// 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:

		SetDlgItemText(hwnd, IDC_PLAY_PAUSE, TEXT("Pause"));
		bPaused = FALSE;
		dwRepetitions = 1;
		bPlaying = 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);
			free(pNewBuffer);
			EndDialog(hwnd, 0);
			return TRUE;
		}
		break;
	}
	return FALSE;
}
Ejemplo n.º 5
0
int CAudioCapture::Start()
{
	MMRESULT res = MMSYSERR_NOERROR;

	if (m_hWaveIn == NULL)
    {
		ZeroMemory(&m_waveHdrA, sizeof(WAVEHDR));
		ZeroMemory(&m_waveHdrB, sizeof(WAVEHDR));
		m_ulCapturedBytes = 0;

		OutputDebugStringW(L"WAV: Starting the Wave capture..\n");

		if ((m_hFile != INVALID_HANDLE_VALUE) ||
			((m_hFile = CreateFile(lpRawFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE))
		{
			return MMSYSERR_NOMEM;
		}

		if ((res = waveInOpen((LPHWAVEIN )&m_hWaveIn, 0, &m_wfx, (DWORD_PTR)waveInProc, 
			(DWORD_PTR)this, (WAVE_FORMAT_DIRECT | CALLBACK_FUNCTION))) == MMSYSERR_NOERROR) 
		{			
			// we want our double buffers to be multiples of 1 second, 500ms or at worst case 100ms
			// so that we can count up the capture time based on buffer fills.
			if (m_wfx.nAvgBytesPerSec > 64000)
			{	// over 512 kbps use 100ms buffers
				m_waveHdrA.dwBufferLength = m_wfx.nAvgBytesPerSec / 10;
				m_waveHdrB.dwBufferLength = m_waveHdrA.dwBufferLength;
			}
			else if (m_wfx.nAvgBytesPerSec > 32000)
			{	// 256-512 kbps use 500ms buffers
				m_waveHdrA.dwBufferLength = m_wfx.nAvgBytesPerSec / 2;
				m_waveHdrB.dwBufferLength = m_waveHdrA.dwBufferLength;
			}
			else
			{	// under 254 kbps use 1s buffers
				m_waveHdrA.dwBufferLength = m_wfx.nAvgBytesPerSec;
				m_waveHdrB.dwBufferLength = m_waveHdrA.dwBufferLength;
			}
			m_waveHdrA.lpData = new char[m_waveHdrA.dwBufferLength];
			m_waveHdrB.lpData = new char[m_waveHdrB.dwBufferLength];

			if ((!m_waveHdrA.lpData) || (!m_waveHdrB.lpData))
			{
				OutputDebugStringW(L"Unable to allocate memory for audio capture buffers\n");
				waveInClose(m_hWaveIn);
				m_hWaveIn = NULL;
				delete [] m_waveHdrA.lpData;
				m_waveHdrA.lpData = NULL;
				delete [] m_waveHdrB.lpData;
				m_waveHdrB.lpData = NULL;
				return MMSYSERR_NOMEM;
			}

			m_bUseBufferA = TRUE;

            if ((res = waveInPrepareHeader(m_hWaveIn, &m_waveHdrA, sizeof(WAVEHDR))) == MMSYSERR_NOERROR)
			{
				if ((res = waveInAddBuffer(m_hWaveIn, &m_waveHdrA, sizeof(WAVEHDR))) == MMSYSERR_NOERROR)
				{
					if ((res = waveInPrepareHeader(m_hWaveIn, &m_waveHdrB, sizeof(WAVEHDR))) == MMSYSERR_NOERROR)
					{
						if ((res = waveInAddBuffer(m_hWaveIn, &m_waveHdrB, sizeof(WAVEHDR))) == MMSYSERR_NOERROR)
						{
							m_hEvents[CAPTURE_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
							m_hEvents[CANCEL_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
							if (m_hEvents[CAPTURE_EVENT] && m_hEvents[CANCEL_EVENT])
							{
								CloseHandle(CreateThread(NULL, 0, threadProc, (LPVOID)this, 0, NULL));
								if ((res = waveInStart(m_hWaveIn)) == MMSYSERR_NOERROR)
								{
									return res;
								}
								SetEvent(m_hEvents[CANCEL_EVENT]);
							}
							else
							{
								CloseHandle(m_hEvents[CAPTURE_EVENT]);
								m_hEvents[CAPTURE_EVENT] = NULL;
								CloseHandle(m_hEvents[CANCEL_EVENT]);
								m_hEvents[CANCEL_EVENT] = NULL;
							}
						}
						waveInUnprepareHeader(m_hWaveIn, &m_waveHdrB, sizeof(WAVEHDR));
					}
				}
				waveInUnprepareHeader(m_hWaveIn, &m_waveHdrA, sizeof(WAVEHDR));
			}
			waveInClose(m_hWaveIn);
			m_hWaveIn = NULL;
			delete [] m_waveHdrA.lpData;
			m_waveHdrA.lpData = NULL;
			delete [] m_waveHdrB.lpData;
			m_waveHdrB.lpData = NULL;
		}
		else 
		{
			if(res == MMSYSERR_ALLOCATED)
			{
				OutputDebugStringW(L"WAV: Wavein: MMSYSERR_ALLOCATED..\n");
			}
			else if(res == MMSYSERR_NODRIVER)
			{
				OutputDebugStringW(L"WAV: Wavein: MMSYSERR_NODRIVER..\n");
			}
			else if(res == MMSYSERR_BADDEVICEID)
			{
				OutputDebugStringW(L"WAV: Wavein: MMSYSERR_BADDEVICEID..\n");
			}
			else if(res == MMSYSERR_NOMEM)
			{
				OutputDebugStringW(L"WAV: Wavein: MMSYSERR_NOMEM..\n");
			}
			else if(res == WAVERR_BADFORMAT)
			{
				OutputDebugStringW(L"WAV: Waven WAVERR_BADFORMAT..\n");
			}
			OutputDebugStringW(L"WAV: Wavin failure..\n");
		}	
	}
	else 
	{
		OutputDebugStringW(L"WAV: Restarting WaveIn capture ..\n");
		m_waveHdrA.dwBytesRecorded = 0;
		m_waveHdrB.dwBytesRecorded = 0;
		m_bUseBufferA = TRUE;
		waveInAddBuffer(m_hWaveIn, &m_waveHdrA, sizeof(WAVEHDR));
		waveInAddBuffer(m_hWaveIn, &m_waveHdrB, sizeof(WAVEHDR));
		OutputDebugStringW(L"WAV: WaveIn capture restarted..\n");
		
	}
	return res;
}
Ejemplo n.º 6
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};                                       // 出力データ格納用変数
    
    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;
            }
        }
    }                                                               //メインループ終わり
}
Ejemplo n.º 7
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;
            }
        }
    }                                                               //メインループ終わり
}
Ejemplo n.º 8
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};                                       // 出力データ格納用変数
    
    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};


    ///////////////////////////////
    //                           //
    //       変数の初期設定      //
    //                           //
    ///////////////////////////////

    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を実行
                        for(i=0;i<FFT_SIZE;i++){
                            xin[i]=x[i]*w[i];                       // 窓関数をかける
                        }
                        fft();                                      // FFT
                        ///////////////////////////
                        //                       //
                        //        FFT処理        //
                        //                       //
                        ///////////////////////////
                        for(i=0;i<FFT_SIZE/2;i++){
                            Xphs[i] = atan2(Xi[i], Xr[i]);          // 位相は保持
                            Xphs[FFT_SIZE-i]=-Xphs[i];              // 奇対称にする
                        }
                        for(i=0;i<FFT_SIZE;i++){
                            Xr[i]=cos(2*M_PI*i/FFT_SIZE+Xphs[i]);   // 振幅は一定として実部を作成
                            Xi[i]=sin(2*M_PI*i/FFT_SIZE+Xphs[i]);   // 振幅は一定として虚部を作成
                        }

                        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;
            }
        }
    }                                                               //メインループ終わり
}
Ejemplo n.º 9
0
int mmio_send_dacs(void)
{
    HMMIO hmmio;
    UINT mmresult;
    HANDLE hFormat;
    int i, j;
    short *sp1, *sp2;
    float *fp1, *fp2;
    int nextfill, doxfer = 0;
    int nda, nad;
    if (!nt_nwavein && !nt_nwaveout) return (0);


    if (nt_meters)
    {
        int i, n;
        float maxsamp;
        for (i = 0, n = 2 * nt_nwavein * DEFDACBLKSIZE, maxsamp = nt_inmax;
            i < n; i++)
        {
            float f = STUFF->st_soundin[i];
            if (f > maxsamp) maxsamp = f;
            else if (-f > maxsamp) maxsamp = -f;
        }
        nt_inmax = maxsamp;
        for (i = 0, n = 2 * nt_nwaveout * DEFDACBLKSIZE, maxsamp = nt_outmax;
            i < n; i++)
        {
            float f = STUFF->st_soundout[i];
            if (f > maxsamp) maxsamp = f;
            else if (-f > maxsamp) maxsamp = -f;
        }
        nt_outmax = maxsamp;
    }

        /* the "fill pointer" nt_fill controls where in the next
        I/O buffers we will write and/or read.  If it's zero, we
        first check whether the buffers are marked "done". */

    if (!nt_fill)
    {
        for (nad = 0; nad < nt_nwavein; nad++)
        {
            int phase = ntsnd_inphase[nad];
            WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
            if (!(inwavehdr->dwFlags & WHDR_DONE)) goto idle;
        }
        for (nda = 0; nda < nt_nwaveout; nda++)
        {
            int phase = ntsnd_outphase[nda];
            WAVEHDR *outwavehdr =
                ntsnd_outvec[nda][phase].lpWaveHdr;
            if (!(outwavehdr->dwFlags & WHDR_DONE)) goto idle;
        }
        for (nad = 0; nad < nt_nwavein; nad++)
        {
            int phase = ntsnd_inphase[nad];
            WAVEHDR *inwavehdr =
                ntsnd_invec[nad][phase].lpWaveHdr;
            if (inwavehdr->dwFlags & WHDR_PREPARED)
                waveInUnprepareHeader(ntsnd_indev[nad],
                    inwavehdr, sizeof(WAVEHDR));
        }
        for (nda = 0; nda < nt_nwaveout; nda++)
        {
            int phase = ntsnd_outphase[nda];
            WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
            if (outwavehdr->dwFlags & WHDR_PREPARED)
                waveOutUnprepareHeader(ntsnd_outdev[nda],
                    outwavehdr, sizeof(WAVEHDR));
        }
    }

        /* Convert audio output to fixed-point and put it in the output
        buffer. */
    for (nda = 0, fp1 = STUFF->st_soundout; nda < nt_nwaveout; nda++)
    {
        int phase = ntsnd_outphase[nda];

        for (i = 0, sp1 = (short *)(ntsnd_outvec[nda][phase].lpData) +
            CHANNELS_PER_DEVICE * nt_fill;
                i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++)
        {
            for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE;
                j++, fp2++, sp2 += CHANNELS_PER_DEVICE)
            {
                int x1 = 32767.f * *fp2;
                if (x1 > 32767) x1 = 32767;
                else if (x1 < -32767) x1 = -32767;
                *sp2 = x1;
            }
        }
    }
    memset(STUFF->st_soundout, 0,
        (DEFDACBLKSIZE *sizeof(t_sample)*CHANNELS_PER_DEVICE)*nt_nwaveout);

        /* vice versa for the input buffer */

    for (nad = 0, fp1 = STUFF->st_soundin; nad < nt_nwavein; nad++)
    {
        int phase = ntsnd_inphase[nad];

        for (i = 0, sp1 = (short *)(ntsnd_invec[nad][phase].lpData) +
            CHANNELS_PER_DEVICE * nt_fill;
                i < 2; i++, fp1 += DEFDACBLKSIZE, sp1++)
        {
            for (j = 0, fp2 = fp1, sp2 = sp1; j < DEFDACBLKSIZE;
                j++, fp2++, sp2 += CHANNELS_PER_DEVICE)
            {
                *fp2 = ((float)(1./32767.)) * (float)(*sp2);
            }
        }
    }

    nt_fill = nt_fill + DEFDACBLKSIZE;
    if (nt_fill == nt_realdacblksize)
    {
        nt_fill = 0;

        for (nad = 0; nad < nt_nwavein; nad++)
        {
            int phase = ntsnd_inphase[nad];
            HWAVEIN device = ntsnd_indev[nad];
            WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
            waveInPrepareHeader(device, inwavehdr, sizeof(WAVEHDR));
            mmresult = waveInAddBuffer(device, inwavehdr, sizeof(WAVEHDR));
            if (mmresult != MMSYSERR_NOERROR)
                nt_waveinerror("waveInAddBuffer: %s\n", mmresult);
            ntsnd_inphase[nad] = WRAPFWD(phase + 1);
        }
        for (nda = 0; nda < nt_nwaveout; nda++)
        {
            int phase = ntsnd_outphase[nda];
            HWAVEOUT device = ntsnd_outdev[nda];
            WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
            waveOutPrepareHeader(device, outwavehdr, sizeof(WAVEHDR));
            mmresult = waveOutWrite(device, outwavehdr, sizeof(WAVEHDR));
            if (mmresult != MMSYSERR_NOERROR)
                nt_waveouterror("waveOutWrite: %s\n", mmresult);
            ntsnd_outphase[nda] = WRAPFWD(phase + 1);
        }

            /* check for DAC underflow or ADC overflow. */
        for (nad = 0; nad < nt_nwavein; nad++)
        {
            int phase = WRAPBACK(ntsnd_inphase[nad] - 2);
            WAVEHDR *inwavehdr = ntsnd_invec[nad][phase].lpWaveHdr;
            if (inwavehdr->dwFlags & WHDR_DONE) goto late;
        }
        for (nda = 0; nda < nt_nwaveout; nda++)
        {
            int phase = WRAPBACK(ntsnd_outphase[nda] - 2);
            WAVEHDR *outwavehdr = ntsnd_outvec[nda][phase].lpWaveHdr;
            if (outwavehdr->dwFlags & WHDR_DONE) goto late;
        }
    }
    return (1);

late:

    nt_logerror(LATE);
    nt_resyncaudio();
    return (1);

idle:

    /* If more than nt_adcjitterbufsallowed ADC buffers are ready
    on any input device, resynchronize */

    for (nad = 0; nad < nt_nwavein; nad++)
    {
        int phase = ntsnd_inphase[nad];
        WAVEHDR *inwavehdr =
            ntsnd_invec[nad]
                [WRAPFWD(phase + nt_adcjitterbufsallowed)].lpWaveHdr;
        if (inwavehdr->dwFlags & WHDR_DONE)
        {
            nt_resyncaudio();
            return (0);
        }
    }

        /* test dac sync the same way */
    for (nda = 0; nda < nt_nwaveout; nda++)
    {
        int phase = ntsnd_outphase[nda];
        WAVEHDR *outwavehdr =
            ntsnd_outvec[nda]
                [WRAPFWD(phase + nt_dacjitterbufsallowed)].lpWaveHdr;
        if (outwavehdr->dwFlags & WHDR_DONE)
        {
            nt_resyncaudio();
            return (0);
        }
    }
#ifdef MIDI_TIMESTAMP
    nt_midisync();
#endif
    return (0);
}